BaseServlet,让一个servlet处理多个请求
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处理多个请求的更多相关文章
- Servlet(五):一个Servlet处理多个请求
一.为什么要使用一个Servlet来处理多个请求? 当浏览器发送了一次请求到服务器时,servlet容器会根据请求的url-pattern找到对应的Servlet类,执行对应的doPost或doGet ...
- 一个servlet处理多个请求(使用Method的反射机制)
方法一 可以通过在请求的时候加上参数,然后在servlet中获取请求的参数,再去调用对应的方法.达到一个servlet处理多个请求的目的 test.jsp: <%@ page language= ...
- 如何用一个servlet处理多个请求
一个servlet处理多个请求,原理:利用反射机制获取在selvlet类中的其他方法1.前端页面<%@ page language="java" contentType=&q ...
- 【WEB小工具】BaseServlet—一个Servlet处理多个请求
package cn.itcast.test.web.servlet; import java.io.IOException; import java.io.PrintWriter; import j ...
- 怎么在一个servlet中实现多个功能 ?如何使一个Servlet处理多个请求?
自学javaweb一直不知道一个servelt可以有多个功能!看了别人代码才知道这个可以有! 平时你建立servelt时候你会吧doget和dopost这两个勾上,要想实现多个功能,你不必要勾选dog ...
- 一个servlet处理多个请求或者叫方法
http://blog.csdn.net/qq_25201665/article/details/52037607
- 一个servlet如何处理多个请求
页面1:表单的action=login?method=login 页面2:表单的action=login?method=insert ..... 然后通过method的值采用不同方法进行处理. 如下 ...
- Tomcat是一个Servlet容器?
"Tomcat是一个Servlet容器",这句话对于2019年的程序员应该是耳熟能详的. 单纯的思考一下这句话,我们可以抽象出来这么一段代码: class Tomcat { Lis ...
- (二)第一个Servlet
一.预备知识 一.Servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个 ...
随机推荐
- jQuery插件——ajax
一.ajax请求 1.load(url, [data], [callback]) 概述:加载远程的HTML文件代码,并插入到指定的DOM节点中. 参数:url:待装入 HTML 网页网址. data: ...
- 文件系统的几种类型:ext3, swap, RAID, LVM
分类: 架构设计与优化 1. ext3 在异常断电或系统崩溃(不洁关机, unclean system shutdown ).每个已挂载ext2文件系统计算机必须使用e2fsck程序来检查其一致性 ...
- PTA中提交Java程序的一些套路
201708新版改版说明 PTA与2017年8月已升级成新版,域名改为https://pintia.cn/,官方建议使用Firefox与Chrome浏览器. 旧版 PTA 用户首次在新版系统登录时,请 ...
- 201521123016《JAVA程序设计》第1周学习总结
本周学习总结 认识了Java包括JDK:Java开发工具包:JRE:Java执行环境:JVM:Java虚拟机 学习了一些JAVA基本语法,如:public class:public static vo ...
- SQL映射文件实现多种方式查询
1.单条件查询在test中代码如下 2.多条件查询时需要把查询条件编辑为对象或者是集合传入,例如 通过对象进行查询 或者是通过集合进行查询列如Map集合 还有就是通过@Param注解实现多参数的入参, ...
- GMF常见问题
1.问题:连接线旁边没有文字标签和箭头 文字标签:在gmfmap里的Connection Mappping下增加Label Mapping元素:箭头:在gmfgraph里为Polyline Conne ...
- ArcGIS连带文字注记导出为CAD格式
可以使用ArcGIS的"Export To CAD"工具将点.线.面等要素直接导出为CAD格式.如果要连带将ArcGIS中的文字标注导出为CAD格式要稍麻烦一点,下面是一个例子. ...
- Android 8.0 功能和 API
Android 8.0 为用户和开发者引入多种新功能.本文重点介绍面向开发者的新功能. 用户体验 通知 在 Android 8.0 中,我们已重新设计通知,以便为管理通知行为和设置提供更轻松和更统一的 ...
- 【个人笔记】《知了堂》前端mySql基础
指定列之后添加: ALTER TABLE 表名 ADD 添加的新列名 INT AFTER 指定列之后 第一个位置: ALTER TABLE 表名 ADD 添加的新列名 varchar(20) AFTE ...
- DialogFragment的应用
一.DialogFragment简单介绍: 1.基本概念 DialogFrament 指一个与fragment建立了关联的Dialog, 随fragment生, 随fragment死, 即Dialog ...