文章目录
一、Request
| request 与 response原理 |
|---|
| 我们知道tomcat会在第一次请求url来创建对应路径映射的servlet对象(如果设置servlet启动时自动创建,则请求url不会重复创建servlet对象) |
| 同时,每一次请求,tomcat会先创建response和request对象,其中request对象中会封装请求消息数据 |
| 然后tomcat会将这两个对象传递给servlet实现类中的service方法,并调用 |
| 我们可以在service方法中,通过response对象来设置响应消息,最后用户通过浏览器可以获取到这些响应数据(这是省略前端的情况下,一般前端工程师会对响应拦截处理) |
| 当然tomcat在响应数据前,会先获取response里面的数据,然后再响应给前端 |
| HttpServletRequest |
|---|


如果你观察Tomcat的源码就会发现,tomcat有一个HttpServletRequest的实现类org.apache.catalina.connector包下的RequestFacade,同时此包下还有一个ResponseFacade是HttpServletResponse接口的实现类


1、获取请求消息数据
1、获取请求行数据
| 请求行格式 |
|---|
| 举例:GET /day1/demo1?name=zhangsan HTTP/1.1 |
GET这个位置:请求方法,可以是POST,DELETE,PUT等等,可通过String getMethod()方法获取 |
/day1:虚拟目录,是在Tomcat设置的,可通过String getContextPath()方法获取 |
/demo1:servlet路径,可通过String getServletPath()方法获取 |
?name=zhangsan:请求参数,可通过String getQueryString()方法获取 |
/day1/demo1:这两个合起来是请求URI,可通过String getRequestURI()方法获取 |
StringBuffer getRequestURL():和上面差不多,只不过它获取的路径会带http://ip地址/day1/demo1 |
HTTP/1.1:协议及版本,可通过String getProtocol()方法获取 |
获取客户机ip地址,可通过String getRemoteAddr()方法获取 |

package com.yzpnb.servlet;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Request快速入门
*/
@WebServlet("/dome1")
public class Dome1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求方法
String method = req.getMethod();
System.out.println("请求方法:"+method);
//获取虚拟目录
String contextPath = req.getContextPath();
System.out.println("虚拟目录:"+contextPath);
//获取servlet路径
String servletPath = req.getServletPath();
System.out.println("servlet路径:"+servletPath);
//获取get请求参数
String queryString = req.getQueryString();
System.out.println("请求参数:"+queryString);
//获取请求URL
String requestURI = req.getRequestURI();
StringBuffer requestURL = req.getRequestURL();
System.out.println("请求路径:"+requestURI+"========"+requestURL);
//获取协议及版本
String protocol = req.getProtocol();
System.out.println("协议及版本:"+protocol);
//获取客户机ip
String remoteAddr = req.getRemoteAddr();
System.out.println("客户机ip:"+remoteAddr);
}
}
2、获取请求头数据
| 方法 |
|---|
String getHeader(String name):通过请求头名称获取请求头(就是键值对的形式) |
Enumeration< String > getHeaderNames():获取所有请求头名称,返回值比较特殊,可以当Enumeration类型为迭代器 |

package com.yzpnb.servlet;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
/**
* Request快速入门
*/
@WebServlet("/dome1")
public class Dome1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取所有请求头名称
Enumeration<String> headerNames = req.getHeaderNames();
System.out.println("所有请求头");
//遍历请求头名称
while(headerNames.hasMoreElements()){//如果没有下一个值则退出循环
String s = headerNames.nextElement();//获取下一个元素
String header = req.getHeader(s);//根据请求头获取请求头值
System.out.println(s+" "+header);
}
/*根据user-agent请求头获取用户所用浏览器版本*/
String userAgent = req.getHeader("user-agent");
if(userAgent.contains("Chrome")){//判断是否包含关键字Chrome
//是谷歌浏览器
System.out.println("很好,这是我们推荐的Chrome浏览器");
}else{
//不是谷歌浏览器
System.out.println("推荐使用谷歌Chrome浏览器");
}
/*根据referer获取用户从哪里点超链接跳转到这里的*/
String referer = req.getHeader("referer");
System.out.println("用户从:"+referer+"来");//注意如果你直接浏览器输入地址进来,会输出null
if(referer != null){//防盗链
if(referer.contains("dome1")){
System.out.println("正常进入链接");
}else{
System.out.println("非正常进入");
}
}else{
System.out.println("直接输入网址进入");
}
}
}
3、请求体数据
| post请求才有请求体 |
|---|
1、先获取输入流对象:BufferReader getReader():获取字符输入流,ServletInputStream getInputStream():获取字节输入流 |
发送post请求,需要用到表单,或者用某些模拟浏览器,如果你不会,应该先去补习,而不是学这个

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取字符流
BufferedReader reader = req.getReader();
//读取数据
String line = null;
while((line = reader.readLine()) != null){
System.out.println(line);
}
}
2、获取数据通用方法
1、获取请求参数通用方法
String getParameter(String name):根据参数名称获取参数值,比如username=zhangsan&age=14,那么我们通过参数名username可以获取对应值zhangsan |
|---|
String[] getParameterValues(String name):根据参数名称获取参数值数组,比如hobby=basketball&hobby=game,通过hobby可以获取数组[basketball,game] |
Enumeration< String > getParameterNames():获取所有请求参数名称 |
Map< String,String[] > getParameterMap():获取所有参数的map集合 |

<%--
Created by IntelliJ IDEA.
User: dell
Date: 2020/10/4
Time: 16:42
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/dome1" method="post">
<input type="text" name="username" placeholder="请输入用户名"/><br/>
<input type="text" name="password" placeholder="请输入密码"/><br/>
<input type="checkbox" name="hobby" value="game"/>游戏
<input type="checkbox" name="hobby" value="basketball"/>篮球<br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>

package com.yzpnb.servlet;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
/**
* Request快速入门
*/
@WebServlet("/dome1")
public class Dome1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//get获取请求参数
//根据参数名称获取值
// String username = req.getParameter("username");
this.doPost(req, resp);//因为代码逻辑相同,我们可以调用doPost方法来简化代码
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//post获取请求参数
//根据参数名称获取值
String username = req.getParameter("username");
System.out.println("username="+username);
System.out.println("==============================");
//根据参数名获取参数数组
String[] hobbies = req.getParameterValues("hobby");
if(hobbies!=null){
System.out.print("hobby=[");
for(String hobby:hobbies){
System.out.print(hobby+",");
}
System.out.println("]");
System.out.println("==============================");
}
//获取所有参数名
Enumeration<String> parameterNames = req.getParameterNames();
while(parameterNames.hasMoreElements()){
String s = parameterNames.nextElement();
System.out.print(s+"=");
String parameter = req.getParameter(s);//无法获取数组
System.out.println(parameter);
}
System.out.println("==============================");
//获取所有参数map集合(解决上面无法获取数组问题)
Map<String, String[]> parameterMap = req.getParameterMap();//获取所有map
Set<String> keySet = parameterMap.keySet();//获取key
for(String key:keySet){//遍历key
String[] values = parameterMap.get(key);//根据key获取value
if(hobbies!=null){//如果有值
System.out.print(key+"=");
for(String value:values){//遍历值
System.out.print(value+" ");
}
System.out.println();
}
}
}
}

| 解决中文乱码 |
|---|
//解决中文乱码,设置流的字符集编码
req.setCharacterEncoding("utf-8");

这时你可能要问,如果用tomcat8以下版本怎么解决中文乱码,放心,就像人们现在都用智能手机,你还会专门回去用小诺基亚么?还会有人专门回去诺基亚研制触屏,上网么?
2、请求转发
| 请求转发 |
|---|
| 一种服务器跳转方式,通常我们一个servlet是完不成一项功能的,一般都是几个servlet配合完成,那么如何在servlet1处理完后跳转到servlet2继续处理呢?就需要请求转发 |
1、RequestDispatcher requestDispatcher = req.getRequestDispatcher(String path);:通过request对象获取请求转发器对象RequestDispatcher |
2、requestDispatcher.forward(ServletRequest servletRequest,ServletResponse servletResponse);:使用请求转发器对象RequestDispatcher的forward方法转发 |

package com.yzpnb.servlet;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
/**
* Request快速入门
*/
@WebServlet("/dome1")
public class Dome1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("我是dome1Get");
// RequestDispatcher requestDispatcher = req.getRequestDispatcher("/dome2");
// requestDispatcher.forward(req,resp);
req.getRequestDispatcher("/dome2").forward(req,resp);//上面那么写太麻烦,一行搞定转发
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码,设置流的字符集编码
req.setCharacterEncoding("utf-8");
System.out.println("我是dome1Post");
// RequestDispatcher requestDispatcher = req.getRequestDispatcher("/dome2");
// requestDispatcher.forward(req,resp);
req.getRequestDispatcher("/dome2").forward(req,resp);//上面那么写太麻烦,一行搞定转发
}
}

package com.yzpnb.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/dome2")
public class Dome2 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("我是dome2Post");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("我是dome2Get");
}
}


| 需要注意的点(面试可能问) |
|---|
| 1、浏览器地址栏并不会发生改变 |
| 2、只能请求转发到服务器内部资源,而不能转发到外部,比如www.baidu.com |
| 3、转发是一次请求,而不是多次,如果细心你会发现我们forward跳转时,都是将request和response对象传入的,也就是说,无论转发多少次,都是同一此请求 |
3、共享数据
| 域对象 |
|---|
| 一个有作用范围的对象,可以在范围内共享数据,不同域对象作用范围不同 |
| request域 |
|---|
| 范围是一次请求,通常用于在多个转发资源中共享数据,比如servlet1转发到2,2转发到3,而就算转发10000次,也都在一次请求中,这就是request域 |
void setAttribute(String name,Object obj):存储一个数据到request域中,name是键,obj是数据,在同一个域中,可通过name获取obj |
Object getAttribute(String name):通过键获取值 |
void removeAttribute(String name):移除指定键值对 |

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码,设置流的字符集编码
req.setCharacterEncoding("utf-8");
System.out.println("我是dome1Post");
//在域中设置值,需要在转发之前
req.setAttribute("name","我是字符串");
req.setAttribute("age",15);
req.setAttribute("array",new String[] {"1","2","3"});
req.getRequestDispatcher("/dome2").forward(req,resp);//上面那么写太麻烦,一行搞定转发
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("我是dome2Post");
String name = (String)req.getAttribute("name");
Integer age = (Integer)req.getAttribute("age");
String[] array = (String[])req.getAttribute("array");
System.out.println(name);
System.out.println(age);
System.out.println(array);
}
移除就不演示了,直接request.removeAttribute("name")这样的就可以将值移除出域
4、获取ServletContext
| ServletContext |
|---|
| 一个非常重要的对象,这里只讲怎么获取,后面会专门讲解此对象 |
ServletContext getServletContext():通过Request对象调用方法获取即可 |

二、HTTP响应协议
| 响应消息 |
|---|
| 前面我们学过请求消息,就是客户端发送给服务端的数据,由请求行,请求头,请求空行,请求体组成 |
| 响应消息:服务端发送给客户端的数据 |
| 响应消息由,响应行,响应头,响应空行,响应体组成 |

| 响应行组成:协议及版本 响应状态码 状态码描述 |
|---|
| 状态码:服务器告诉客户端浏览器本次请求与响应的状态,一般由3位数字组成,比如404,502,可以百度HTTP状态码来详细了解分类,下面简单介绍一下状态码分类 |
| 状态码分类(XX代表随机数字):1XX(表示服务端接收消息,接收了一半,没接收完,等了一段时间只能发送状态码1XX),2XX(表示成功),3XX(302代表重定向,比如我们平常登陆完成后出现5秒后跳转页面,这时跳转去的页面就是重定向页面。304代表访问缓存,比如你的头像,第一次访问后服务器反馈给你,下次你又来请求相同的内容,这时就没必要重复响应,服务器会告诉浏览器你本地有,去访问缓存就行了),4XX(表示客户端错误,404表示你请求的资源不存在,一般路径写错就会报这个错,405表示请求方法不对,比如你发Post请求,而后端只有处理Get请求的方法),5XX(表示服务器错误,一般后端代码出错会报这个错) |
| 响应头 |
|---|
| Content-Type:表示响应体数据格式以及编码格式 |
Content-disposition:表示以何种格式打开响应体,没有指定就使用默认值in-line,表示在当前页面打开,一般我们需要指定时使用attachment;filename=XXX,表示以附件形式打开响应体,比如下载时指定使用,filename指定文件名 |
三、Response
设置响应信息和设置请求信息差不多,就不多赘述了
| 设置响应行、响应头 |
|---|
setStatus(int sc):设置;响应行状态码 |
setHeader(String name,String value):设置响应头 |

| 设置响应头 |
|---|
1、获取输出流(字符输出流PrintWriter getWriter(),字节输出流ServletOutputStream getOutputStream()。) |
| 2、使用输出流将数据响应给客户端浏览器 |
1、response重定向
| 服务器端重定向 |
|---|
| 就是用户发送请求到一个servlet,服务器告诉用户这个servlet办不了,你去找X某某办 |
| 1、重定向需要给浏览器设置状态码302 |
| 2、需要告诉浏览器重定向路径,需设置location |


@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("我是dome1Get");
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码,设置流的字符集编码
req.setCharacterEncoding("utf-8");
System.out.println("我是dome1Post");
/*dome1重定向到dome2*/
//设置状态码为302
// resp.setStatus(302);
//设置响应头location
// resp.setHeader("location","dome2");
//上面两行代码,302和location都是固定的,能变得只有dome2这个路径,所以有一个更简单的方法
resp.sendRedirect("dome2");
}

| 重定向特点(与请求转发完全相反) |
|---|
| 地址栏会随着重定向而改变 |
| 重定向几次就发送几次请求,也就是不能用request域来传递数据了,因为都不是同一次请求 |
| 重定向可以访问到其它站点,而不局限与本服务器资源 |
2、response相对/绝对路径
| 因为这个是初学者非常容易犯的错,所有特地挑出来讲解 |
|---|
| 绝对地址:http://ip地址/资源路径 |
| 相对地址:/资源路径 |
| 以/开头的是相对路径,不以/开头的是绝对路径 |
| 相对路径会相对于当前路径范围下,寻找指定资源 |
| 绝对路径会根据路径直接寻找资源 |
| 建议给客户端使用的重定向,加上虚拟目录,虚拟目录最好不要写死,以后改一下,要改很多地方,推荐使用request.getContextPath()动态获取虚拟目录 |
3、response输出数据

| 最大的问题 |
|---|
| 就是服务器响应与浏览器编码不一样,会乱码 |
| 那么响应头中Content-Type参数可以设置编码格式 |
| 通过设置响应头来规定编码 |

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("我是dome1Get");
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码,设置流的字符集编码
req.setCharacterEncoding("utf-8");
// resp.setCharacterEncoding("utf-8");//响应时也需要设置编码,默认流编码为ISO-8859-1
// resp.setHeader("content-type","text/html;charset=utf-8");//这一行的功能将上一行也包括了
//同样的,和重定向一样,这个设置编码也提供了简单形式
resp.setContentType("text/html;charset=utf-8");
System.out.println("我是dome1Post");
//获取字符输出流
// PrintWriter writer = resp.getWriter();
// writer.write("<h1>字符输出流<h1/>");
//获取字节输出流,注意,同一次响应,只能使用一种输出流,如果想测试字符输出,先将下面这两句注释,然后放开上面两句测试
ServletOutputStream outputStream = resp.getOutputStream();
outputStream.write("alksdjflkasjfl案例可使肌肤鲁大师".getBytes("utf-8"));//只要确保内容转换为字节即可输出
}
4、response验证码
| 简单的验证码例子,可不要把这种验证码放在项目中用 |
|---|

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("我是dome1Get");
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码,设置流的字符集编码
req.setCharacterEncoding("utf-8");
// resp.setCharacterEncoding("utf-8");//响应时也需要设置编码,默认流编码为ISO-8859-1
// resp.setHeader("content-type","text/html;charset=utf-8");//这一行的功能将上一行也包括了
//同样的,和重定向一样,这个设置编码也提供了简单形式
// resp.setContentType("text/html;charset=utf-8");
int width = 100;//生成图片的宽
int height = 50;//生成图片的高
//1、创建一个对象,在内存中代表一个图片
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//创建图片对象
/*2、美化图片*/
//2.1填充背景色
Graphics graphics = bufferedImage.getGraphics();//创建绘画对象
graphics.setColor(Color.PINK);//设置画笔颜色
graphics.fillRect(0,0,width,height);//填充一个矩形区域,从(0,0)开始
//2.2画边框
graphics.setColor(Color.BLUE);//重新设置画笔颜色
graphics.drawRect(0,0,width-1,height-1);//画一个框框,-1是因为这个对象只有100*50,而边框有1像素,会跑到对象外面而看不见
//2.3生成验证码
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
for(int i = 1;i < 5;i++){
int index = random.nextInt(str.length());//获取随机下标
char ch = str.charAt(index);//拿到随机字符
graphics.drawString(ch+"",width/5*i,height/2);//画字符
}
//3、将图片输出到页面上
ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());
}

四、ServletContext对象
| ServletContext |
|---|
| 代表整个web应用,可以和整个程序的容器(比如servlet,Tomcat等等)通信 |
| 可以获取MIME类型 |
| 可以作为域对象,共享数据 |
| 获取文件的真实路径(服务器路径) |
| 获取 |
|---|
| 1、通过request对象获取:request.getServletContext(); |
| 2、直接通过HttpServlet获取(因为HttpServlet继承Servlet接口):this.getServletContext(); |



@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("我是dome1Get");
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码,设置流的字符集编码
req.setCharacterEncoding("utf-8");
// resp.setCharacterEncoding("utf-8");//响应时也需要设置编码,默认流编码为ISO-8859-1
// resp.setHeader("content-type","text/html;charset=utf-8");//这一行的功能将上一行也包括了
//同样的,和重定向一样,这个设置编码也提供了简单形式
// resp.setContentType("text/html;charset=utf-8");
//1、通过request对象获取ServletContext对象
ServletContext servletContext1 = req.getServletContext();
//2、通过HttpServlet直接获取
ServletContext servletContext2 = this.getServletContext();
//结果为true,无论何处获取,同一工程下只有一个ServletContext对象
System.out.println("两种方式获取的ServletContext是否是同一个对象:"+(servletContext1 == servletContext2));
/*
获取MIME类型
* 在互联网通信过程中定义的一种文件数据类型
格式:大类型/小类型 比如text/html text表示纯文本 html表示html文档 再比如 image/jpeg
作用,再给客户端响应数据时,先要了解类型格式,响应时响应头中的Content-Type要指定对应的格式,这样浏览器才能正确接收
获取方法
String getMimeType(String file) 通过文件后缀名获取MIME类型
* */
//定义文件名称
String fileName = "a.jpg";
//获取MIME文件类型
String MimeType = servletContext1.getMimeType(fileName);
System.out.println("文件a.jpg对应的MIME类型为:"+MimeType);
/*
ServletContext对象作为域对象的作用域是最大的
因为它的作用范围是整个web程序
设置值,获取值的方法和请求域相同,getAttribute这些方法,是所有域对象通用的
*/
//设置一个值到ServletContext域,那么整个web程序任何地方,只要这条语句执行过,就可以获取到
servletContext1.setAttribute("name","zhangsan");
/*
* 获取文件真实路径
*
* String getRealPath("")
*/
String realPath = servletContext1.getRealPath("/index.jsp");// 一个/ 后面跟资源名称,就是我们web或webapp目录下的资源
//如果你要获取WEB-INF下面资源,需要些/WEB-INF/XXX.xxx
System.out.println(realPath);
//创建文件对象时,经常需要文件绝对路径,那么通过这个获取非常高效
File file = new File(realPath);
}
五、文件下载
| 步骤 |
|---|
1、设置响应头,告诉浏览器文件打开方式为附件打开,Content-disposition:attachment;filename=XXX,表示以附件形式打开响应体 |
| 2、用输入流读取文件,转到输出流输出 |

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("我是dome1Get");
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码,设置流的字符集编码
req.setCharacterEncoding("utf-8");
ServletContext servletContext = req.getServletContext();//获取ServletContext
//1、获取文件的真实路径
String realPath = servletContext.getRealPath("/index.jsp");
//2、用字节流关联
FileInputStream fileInputStream = new FileInputStream(realPath);
//3、设置响应头,让浏览器以附件打开响应体
//3.1获取文件MIME类型并设置
String mimeType = servletContext.getMimeType("index.jsp");
resp.setHeader("content-type",mimeType);
//3.2设置以附件方式打开
resp.setHeader("content-disposition","attachment;filename=index.jsp");
//4、将输入流数据写出,标准的输入流数据转到输出流写法
ServletOutputStream outputStream = resp.getOutputStream();
byte[] bytes = new byte[1024 * 8];
int len = 0;
while((len = fileInputStream.read(bytes)) != -1){
outputStream.write(bytes,0,len);
}
fileInputStream.close();
}
1、中文文件名乱码问题
| 中文文件名问题,中文文件名无法正常获取显示 |
|---|
| 1、获取客户端浏览器版本信息 |
| 2、根据不同版本信息,响应不同的数据(设置filename文件名的编码方式) |

package com.yzpnb.utils;
import sun.misc.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class DownloadUtils {
public static String getFileName(String agent,String filename) throws UnsupportedEncodingException {
if(agent.contains("MSIE")){
//IE浏览器
filename = URLEncoder.encode(filename,"utf-8");
filename = filename.replace("+"," ");
} else if(agent.contains("Firefox")){
//火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?"+base64Encoder.encode(filename.getBytes("utf-8"))+"?=";
} else{
//其它浏览器
filename = URLEncoder.encode(filename,"utf-8");
}
return filename;
}
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码,设置流的字符集编码
req.setCharacterEncoding("utf-8");
ServletContext servletContext = req.getServletContext();//获取ServletContext
String fileName = "你好.txt";
//1、获取文件的真实路径
String realPath = servletContext.getRealPath("/"+fileName);
//2、用字节流关联
FileInputStream fileInputStream = new FileInputStream(realPath);
//3、设置响应头,让浏览器以附件打开响应体
//3.1获取文件MIME类型并设置
String mimeType = servletContext.getMimeType(fileName);
resp.setHeader("content-type",mimeType);
/**解决中文文件名*/
//1、获取user-agent请求头,拿到浏览器版本
String userAgent = req.getHeader("user-agent");
fileName = DownloadUtils.getFileName(userAgent, fileName);
//3.2设置以附件方式打开
resp.setHeader("content-disposition","attachment;filename="+fileName);
//4、将输入流数据写出,标准的输入流数据转到输出流写法
ServletOutputStream outputStream = resp.getOutputStream();
byte[] bytes = new byte[1024 * 8];
int len = 0;
while((len = fileInputStream.read(bytes)) != -1){
outputStream.write(bytes,0,len);
}
fileInputStream.close();
}
本文深入讲解Servlet中的Request和Response对象的使用方法,包括获取请求消息数据、设置响应信息、文件下载等内容。
1129

被折叠的 条评论
为什么被折叠?



