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. C# xml增删查改

    C# XML XmlDocument 添加命名空间: using System.Xml; 定义公共对象: XmlDocument xmldoc ; XmlNode xmlnode ; XmlEleme ...

  2. 四,ESP8266 TCP服务器

    我要赶时间赶紧写完所有的内容....朋友的东西答应的还没做完呢!!!!!!!没想到又来了新的事情,,....... 配置模块作为TCP服务器然后呢咱们连接服务器发指令控制继电器吸合和断开 控制的指令呢 ...

  3. 九度OJ 1013 开门人和关门人

    #include <iostream> #include <string.h> #include <sstream> #include <math.h> ...

  4. 姑娘你大胆地往前走——答大二学生XCL之八问

    姑娘你大胆地往前走--答大二学生XCL之八问 以下问题的答案写给我家正在读大二的XCL. 写于 2017-9-13 晚 请问您是为什么选择了IT行业的? 与其说是我选择了行业,不如说是行业选择了我. ...

  5. 英语APP体验

    第一部分 1.下载并使用,描述最简单直观的个人第一次上手体验. 感觉不是很好用,可能是个人习惯吧,之前用的都是扇贝单词和有道词典,所以不是特别顺手. 2.找出几个功能性的比较严重的 bug 在口语挑战 ...

  6. 201521123118《java程序与设计》第6周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...

  7. video标签

    Video标签的使用 Video标签含有src.poster.preload.autoplay.loop.controls.width.height等几个属性, 以及一个内部使用的标签<sour ...

  8. Ubuntu16.04安装piwik3.0.1

    1.安装PHP环境 sudo apt-get install php7.0-fpm   2.下载piwik3.0.1 https://piwik.org/download/ 下载后解压到/var/ww ...

  9. ArcGIS连带文字注记导出为CAD格式

    可以使用ArcGIS的"Export To CAD"工具将点.线.面等要素直接导出为CAD格式.如果要连带将ArcGIS中的文字标注导出为CAD格式要稍麻烦一点,下面是一个例子. ...

  10. jsonp其实很简单【ajax跨域请求】

    js便签笔记(13)——jsonp其实很简单[ajax跨域请求] 前两天被问到ajax跨域如何解决,还真被问住了,光知道有个什么jsonp,迷迷糊糊的没有说上来.抱着有问题必须解决的态度,我看了许多资 ...