BaseServlet

  第一次学习servlet的时候是跟着传智播客免费的教学视频,其中崔希凡讲的是我学过自认讲的最好的一位,BaseServlet也是跟着他写过一次,当时很多东西不能理解,后来慢慢发现其中的内层深意,本工具类在崔老师的基础之上增加了文件下载功能,如果能很好掌握,非常有利对struts2的掌握!


1. 我们希望在一个Servlet中可以有多个请求处理方法!
2. 客户端发出请求时,必须给出一个参数,来说明要调用哪一个方法
3. 客户端必须传递名为method的参数

http://localhost:8080/test/UserServlet?method=login、http://localhost:8080/test/UserServlet?method=regist等等

原理

  BaseServlet中调用request.getParameter("method")来确定你需要调用的方法,因为每次请求都是执行service方法,所以通过反射来执行

BaseServlet

package hui.zhang.servlet;

import hui.zhang.down.DownUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List; import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils; /**
* BaseServlet
* 我们希望在一个Servlet中处理多个请求
* 创建Servlet时继承本类而不是继承HttpServlet,重写service方法
* 客户端在发起请求时需要传递method参数来判断调用哪个方法
* eg:http://localhost:8080/test/UserServlet?method=login
* 返回值"f:/xxx"为转发、"r:/xxx"为重定向、"d:/xxx"为下载
* 重定向可以重定向到其他项目中,写法:"r:/192.168.11.24:8080/example/index.jsp"
* 下载可以下载服务器中目录下的文件 "d:/WEB-INF/a.jpg"
* 也可以下载磁盘绝对路径下的文件 "d:/G:/a.jpg"
* @author hui.zhang
*
*/
@SuppressWarnings("serial")
public class BaseServlet extends HttpServlet {
@Override
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");//处理响应编码 //获取传递的method参数
String methodName = request.getParameter("method");
if (methodName == null || methodName.trim().isEmpty()) {
throw new RuntimeException("没有传递method参数,不能确定要调用的方法!");
}
//得到当前类的class对象
Class c = getClass();
Method method = null;
try {
method = c.getMethod(methodName,
HttpServletRequest.class,HttpServletResponse.class);
} catch (Exception e) {
throw new RuntimeException("要调用的方法:"+methodName+"(HttpServletRequest,HttpServletResponse),不存在!",e);
}
//调用method表示的方法
try {
String result = (String)method.invoke(this, request,response);
/*
* 获取请求处理方法执行后返回的字符串,它表示转发或重定向的路径
* 如果返回为null或者"",什么也不做
* 判断返回值中是否存在冒号,如果没有默认转发,因为转发的情况较多
* 如果有冒号,分割,得到前缀f表示forward,前缀r表示redirect
* 后缀为要转发或重定向的路径
*/
if (result == null || result.trim().isEmpty()) {
return;
}
if (result.contains(":")) { //"f:/index.jsp"
int index = result.indexOf(":");
String s = result.substring(0, index); //f
String path = result.substring(index+1); // "/index.jsp"
if (s.equalsIgnoreCase("r")) {
// "/192.168.11.24:8080/example/index.jsp"
if (path.contains(":")) { //有:说明有端口号是其他项目的路径
if (path.contains("http")) {
// "/http://192.168.11.24:8080/example/index.jsp"
response.sendRedirect(path.substring(1));
} else {
response.sendRedirect("http://"+path.substring(1));
}
} else {
response.sendRedirect(request.getContextPath()+path);
}
} else if (s.equalsIgnoreCase("f")) {
request.getRequestDispatcher(path).forward(request, response);
} else if (s.equalsIgnoreCase("d")) { //表示下载
/**
* 两个头一个流
* 1. Content-Type
* 2. Content-Disposition
* 3. 流:下载文件的数据
*/
// path = "/WEB-INF/mp3/自娱自乐.mp3";
// path = "/G://a.jpg";
int indexOf = path.lastIndexOf("/");
String name = path.substring(indexOf); // /自娱自乐.mp3
//如果包含:,说明是绝对路径
String filename = null;
if (path.contains(":")) {
filename = path.substring(1);
} else { //说明是服务器端文件,需要获得绝对路径
//获得文件的绝对路径
filename = this.getServletContext().getRealPath(path);
}
//去掉文件名前的/
name = name.substring(1); // 自娱自乐.mp3
//通过DownUtils工具类处理不同浏览器下载时中文名乱码问题
String framename = DownUtils.filenameEncoding(name, request);
//头1:获得要下载的文件MIME类型
String contentType = this.getServletContext().getMimeType(filename);
//头2:ContentDisposition
String contentDisposition = "attachment;filename="+framename;
FileInputStream input = new FileInputStream(filename);
response.setHeader("Content-Type", contentType);
response.setHeader("Content-Disposition",contentDisposition);
ServletOutputStream output = response.getOutputStream();
IOUtils.copy(input, output);
input.close();
output.close();
} else {
throw new RuntimeException("操作:"+s+"目前还不支持!");
} } else { //默认转发
request.getRequestDispatcher(result).forward(request, response);
}
} catch (Exception e) {
throw new RuntimeException("调用的方法:"+methodName+"(HttpServletRequest,HttpServletResponse),内部抛出异常!", e);
} } }

DownUtils

/**
* 文件下载时处理浏览器不同编码的中文乱码
* @author hui.zhang
* @date 2017-10-12 下午6:04:06
*/
public class DownUtils {
public static String filenameEncoding(String filename, HttpServletRequest request) throws IOException{
//获取浏览器头信息
String agent = request.getHeader("User-Agent");
if(agent.contains("Firefox")){
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?"+base64Encoder.encode(filename.getBytes("utf-8"))+"?=";
} else if(agent.contains("MSIE")){
filename = URLEncoder.encode(filename,"utf-8");
} else {
filename = URLEncoder.encode(filename,"utf-8");
}
return filename;
} }

  代码中注释还算清楚,下载文件的功能是新加上的,测试还挺正常,如果使用出现问题欢迎提出!因为getParameter()在上传文件中失效,所以没写在Base中,后续也会传上来共同交流,感谢观看!

BaseServlet,让一个servlet处理多个请求的更多相关文章

  1. Servlet(五):一个Servlet处理多个请求

    一.为什么要使用一个Servlet来处理多个请求? 当浏览器发送了一次请求到服务器时,servlet容器会根据请求的url-pattern找到对应的Servlet类,执行对应的doPost或doGet ...

  2. 一个servlet处理多个请求(使用Method的反射机制)

    方法一 可以通过在请求的时候加上参数,然后在servlet中获取请求的参数,再去调用对应的方法.达到一个servlet处理多个请求的目的 test.jsp: <%@ page language= ...

  3. 如何用一个servlet处理多个请求

    一个servlet处理多个请求,原理:利用反射机制获取在selvlet类中的其他方法1.前端页面<%@ page language="java" contentType=&q ...

  4. 【WEB小工具】BaseServlet—一个Servlet处理多个请求

    package cn.itcast.test.web.servlet; import java.io.IOException; import java.io.PrintWriter; import j ...

  5. 怎么在一个servlet中实现多个功能 ?如何使一个Servlet处理多个请求?

    自学javaweb一直不知道一个servelt可以有多个功能!看了别人代码才知道这个可以有! 平时你建立servelt时候你会吧doget和dopost这两个勾上,要想实现多个功能,你不必要勾选dog ...

  6. 一个servlet处理多个请求或者叫方法

    http://blog.csdn.net/qq_25201665/article/details/52037607

  7. 一个servlet如何处理多个请求

    页面1:表单的action=login?method=login 页面2:表单的action=login?method=insert ..... 然后通过method的值采用不同方法进行处理. 如下 ...

  8. Tomcat是一个Servlet容器?

    "Tomcat是一个Servlet容器",这句话对于2019年的程序员应该是耳熟能详的. 单纯的思考一下这句话,我们可以抽象出来这么一段代码: class Tomcat { Lis ...

  9. (二)第一个Servlet

    一.预备知识 一.Servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个 ...

随机推荐

  1. javascript中=,==,与===的区别;以及特殊值NaN的讲解

    1.在js中"="是作为赋值.var a;  a=3:给a赋值为3. 2."=="称作相等,"==="被称作严格相等.当使用"== ...

  2. Mac系统的终端显示git当前分支

    当我第一次在mac系统下使用git的时候,发现一个问题,git默认是不显示当前所在的分支名称,然后网上查找资料,找到了解决办法,终于可以显示本地当前分支,现在分享如下. 1 进入你的home目录 cd ...

  3. 简单的独享smb

    1.是这样的,因为办公区域有一个千兆的交换机,但是我的台式机硬盘有点小,500G的,就把一个旧的台式网卡换成了千兆的,装了个CentOS6.5,最小化的,装了个samba,就开始用了: 2.由于是自己 ...

  4. 【Beta】阶段 第三次Daily Scrum Meeting

    每日任务 ·1.本次会议为第三次 Meeting 会议 ·2.本次会议在周三上午9:40召开,会议时间为10分钟 一.今日站立式会议照片 二.每个人的工作(有work item的ID) 三.工作中遇到 ...

  5. 201521123079《java程序设计》第3周学习总结

    1. 本周学习总结 2. 书面作业 1.代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; p ...

  6. 201521123096《Java程序设计》第十四周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...

  7. 201521123113《Java程序设计》第13周学习总结

    1. 本周学习总结 2. 书面作业 Q1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? 返回的结果 ...

  8. 201521123099 《Java程序设计》 第10周学习总结

    1. 本周学习总结 2. 书面作业 本次PTA作业题集异常.多线程 finally 题目4-2 1.1 截图你的提交结果(出现学号) 1.2 4-2中finally中捕获异常需要注意什么? final ...

  9. SSH复用代码最终版

    web.xml文件 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="h ...

  10. Oracle_Sequence如何初始化开始值

    Sequence的start with 值如何确定才能保证生成的主键不会冲突??? 我的项目中最开始数据库表主键的生成策略是 increment,但由于后来采用了集群部署的方式,出现了主键冲突的问题. ...