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. MPLS VPN随堂笔记1

    MPLS VPN 基础 1.MPLS vpn架构的特点 1.1.允许不同CE传递相同私网路由 1.2.SP内部(所有P路由器)不需要学习CE路由 1.3.无安全保障但有带宽保障(跟SP租用服务) 2. ...

  2. MITNIK ATTACK

    Https 443 http 80 TCP/IP 协议栈:将数据封装包头 传输层报头 Ack回复确认位 FIN结束位 SIN 开始位 RST 重置位 Seq 序号位 网络层报头 目的地址 原地址 报文 ...

  3. Coding使用方法

    首先在码市coding.net上创建账号 基础配置 1. 首先,下载安装git客户端和tortoisegit(就是小乌龟,本地右键使用的,跟SVN一样的那个小乌龟). git下载官网:https:// ...

  4. 事后诸葛亮分析(Beta阶段)

    设想和目标 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 解决用户想要随时锻炼四则运算能力的问题:定义的很清楚:有清晰描述. 2.是否有充足的时间来做计划? ...

  5. 测试与发布(Alpha版本)

    [Alpha阶段]测试报告 1.测试找出的BUG (1).这种情况刷新就好 (2).文件必须10个才行,多余10个的部分不会进入查重的部分,少于会出错: (3).文件保存在d:\files,由于有些原 ...

  6. spring在扫描包中的注解类时出现Failed to read candidate component错误

    出现:org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate componen ...

  7. Swing-布局管理器之BorderLayout(边界布局)-入门

    注:本文内容基本源于Java图形化界面设计——布局管理器之BorderLayout(边界布局),笔者学习过程中根据自身理解进行少量编辑. 边界布局管理器(BorderLayout)把容器的的布局分为五 ...

  8. 201521123054《Java程序设计》第1周学习总结

    #1. 本章学习总结 你对于本章知识的学习总结 本章我们学习了各种java相关文件的使用,能够进行基本的程序操作: 学会使用博客.码云与PTA管理java: #2. 书面作业 1.为什么java程序可 ...

  9. 201521123077 《Java程序设计》第11周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 线程的同步(加锁防止多个线程同时访问) synchronized关键字修饰 可以使用于方法前或者方法内做同步 ...

  10. 201521123034《Java程序设计》第十一周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 多线程的冲突 互斥共享(有时两个或两个以上的线程需要同时对 而线程之间如果不加以控制,会产生一种情况-竞争) sy ...