Servlet技术
文章目录
-
- 一、HTTP协议
-
- 1.1 URL格式
- 1.2 HTTP协议特点
- 1.3 HTTP请求
- 1.4 HTTP响应
- 二、Tomcat服务器
-
- 2.1 什么是Tomcat服务器
- 2.2 Tomcat目录结构
- 2.3 IDEA配置Tomcat
- 三、Servlet概述
-
- 3.1 什么是Servlet?
- 3.2 Servlet开发步骤
- 3.3 Servlet的实现
- 3.4 Servlet生命周期
- 3.5 HttpServletRequest对象
-
- 3.5.1 接收请求
- 3.5.2 获取请求参数
- 3.5.3 请求乱码问题
- 3.5.4 请求转发
- 3.5.5 request作用域
- 3.6 HttpServletResponse对象
-
- 3.6.1 响应数据
- 3.6.2 响应乱码
- 3.6.3 重定向
- 3.7 Cookie对象
-
- 3.7.1 Cookie的创建和发送
- 3.7.2 Cookie的获取
- 3.7.3 Cookie设置到期时间
- 3.7.4 Cookie的注意点
- 3.7.5 Cookie的路径
- 3.8 HttpSession对象
-
- 3.8.1 标识符JSESSIONID
- 3.8.2 Session域对象
- 3.8.3 Session对象的销毁
- 3.9 ServletContext对象
-
- 3.9.1 ServletContext对象的获取
- 3.10 文件上传和下载
-
- 3.10.1 文件上传
- 3.10.2 文件下载
一、HTTP协议
HTTP协议(Hypertext Transfer Protocol,即超文本传输协议),是一个客户端请求和响应的标准协议,该协议规定了浏览器与服务器之间交互的一种规则。
1.1 URL格式
URL(统一资源定位符),要访问网络中资源,就必须告诉网络服务器你要请求的资源在哪里,而说明资源位置的就是URL。通俗来讲,就是我们平常在浏览器地址栏输入的http://www.baidu.com/...
。
如下就是URL格式:
1.2 HTTP协议特点
1. 支持C/S模式。2. 简单快速:客户向服务器请求时,只需要传送请求方法和路径。请求方法有`GET`和`POST`。由于HTTP协议较为简单,因而通信速度很快。3. 灵活:HTTP允许任意类型的数据对象。4. 无连接:无连接表示每次连接只处理一个请求。服务器处理完客户请求,并收到客户端回应之后,就断开连接。 **HTTP 1.1版本之后支持可持续连接**。通过这种连接,就可以建立一个TCP连接,一次连接可以发送多个请求并响应。5. 无状态:HTTP协议是无状态协议。**无状态是指协议对事物处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则需要进行重传。**
1.3 HTTP请求
HTTP请求由三部分构成,分别是:请求行、请求头、请求正文。另外,GET请求没有请求正文,所有参数都是直接卸载地址栏。
请求行:请求方式(GET/POST) + 请求路径 + 请求协议版本
**请求头:**一些描述请求内容的键值对
请求正文:真正的请求内容(只有POST请求才会有)
1.4 HTTP响应
在接收到客户端请求后,服务器会返回一个响应信息。HTTP响应由三个部分组成:状态行、消息报头、响应正文(浏览器中看到的内容)。
二、Tomcat服务器
2.1 什么是Tomcat服务器
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
2.2 Tomcat目录结构
bin:启动和关闭Tomcat的bat文件
conf:server.xml
用于配置server相关信息;web.xml
文件配置web应用;tomcat-user.xml
配置用户名密码和权限
lib:该目录防止运行tomcat的jar包
logs:存放日志
webapps:放置部署在Tomcat服务器上的应用
work:该目录用于存放jsp被访问后生成对应的server文件和.class文件
2.3 IDEA配置Tomcat
关于Tomcat的详细配置可以点击该链接查看IDEA配置Tomcat,不同版本可能会有稍许不同,遇到一些小问题上网查找即可。
三、Servlet概述
3.1 什么是Servlet?
-
Servlet是JavaEE规范之一。(接口)
-
Servlet是JavaWeb三大组件之一。(Servlet程序、Filter过滤器、Listener监听器)
-
Servlet是运行在服务器上的一个java小程序,它可以接受客户端发送过来的请求,并响应数据。
3.2 Servlet开发步骤
- 编写一个类去实现Servlet接口
- 重写Servlet生命周期的方法。一般重写doGet(),doPost(),destroy()和service()方法。
- 在生命周期中编写业务功能代码。
- 修改web.xml配置servlet(此步骤不成功,则步骤三报错404)
- 发布到服务器并启动服务器。
- 在浏览器输入网址调用服务器的Servlet程序。
3.3 Servlet的实现
-
创建web项目
-
实现Servlet规范(接口)
实现Servlet规范,即继承HttpServlet类,该类已经完成了通信规则,我们只需要进行业务实现即可。
package com.zs.servlet;import javax.servlet.http.HttpServlet;public class Servlet01 extends HttpServlet { }
-
重写service方法、设置注解
对于Servlet的实现其实也可以重写
doGet
和doPost
方法,因为service方法的底层使用了doGet和doPost方法,但是service方法相较而言更方便,使用也更多。package com.zs.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;/** * 实现servlet * 1.创建普通java类 * 2.让该类继承HttpServlet类 * 3.重写里面的service方法 * 4.设置注解,指定访问的路径 -----也可以通过xml进行配置,注解方式更简单、方便 */@WebServlet("/servlet01")//路径中的'/'不要忘记public class Servlet01 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("Hello Servlet!"); resp.getWriter().write("Hello servlet! This is response!"); }}
测试结果:
-
服务器配置
3.4 Servlet生命周期
Servlet没有main()方法,不能单独运行,它的运行完全由Servlet引擎来控制和调度。所谓的生命周期,其实就是servlet容器何时创建servlet实例、何时调用其方法进行请求处理、何时销毁其实例的过程。
-
实例和初始化时机
当请求到达容器时,查找该servlet对象,不存在则创建并初始化。
-
就绪/调用/服务阶段
有请求到达容器时,容器调用service()方法,处理请求的方法可以被多次调用;HttpServlet的service方法会依据请求方式来调用
doGet()
或doPost()
方法。但是这两个方法默认情况下会抛出异常,因此需要子类去重写。 -
销毁
当容器关闭时,会销毁掉程序中的servlet实例。
package com.zs.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;/** * 实现servlet * 1.创建普通java类 * 2.让该类继承HttpServlet类 * 3.重写里面的service方法 * 4.设置注解,指定访问的路径 -----也可以通过xml进行配置,注解方式更简单、方便 */@WebServlet("/servlet01")public class Servlet01 extends HttpServlet { //init()方式只会在创建实例对象时调用一次,往后的执行过程中不会调用该方法 @Override public void init() throws ServletException { System.out.println("这是初始化方法"); } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("Hello Servlet!"); resp.getWriter().write("Hello servlet! This is response!"); } //服务器关闭或应用程序停止时执行,由系统自动调用,只执行一次 @Override public void destroy() { System.out.println("这是销毁方法"); }}
3.5 HttpServletRequest对象
HttpServletRequest对象:主要作用是用来接收客户端请求发送过来的信息。例如,请求的参数、请求方式、请求头信息等。
目前,HttpServletRequest是ServletRequest的唯一子接口,有人可能会想,既然只有一个子接口,那为什么不将二者合二为一?
其实,从长远角度来讲,是为了在将来有其他更多协议的时候,只需要实现ServletRequest接口就可以了。不得不说,设计者还是考虑得很周到。
3.5.1 接收请求
-
常用方法
方法 描述 getRequestURL() 获取客户端发出请求时的完整URL,返回类型为 StringBuffer
getRequestURI() 获取请求行中的资源名称部分(项目名称开始),返回类型 String
getQueryString() 获取请求行中的参数部分 getMethod() 获取客户端请求方式 getProtocol() 获取HTTP版本号 getContextPath() 获取webapp名字 -
示例
package com.zs.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("/reqservlet")public class RequestServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /*常用方法*/ //获取请求时的完整路径(从http开始,到?前面结束) String requestURL = req.getRequestURL().toString(); //获取请求时的部分路径(从项目名称开始到?结束) String requestURI = req.getRequestURI(); //获取请求时的参数字符串 String queryString = req.getQueryString(); //获取请求方式(GET POST) String method = req.getMethod(); //获取协议版本 String protocol = req.getProtocol(); //获取项目站点名(项目对外访问路径) String contextPath = req.getContextPath(); System.out.println("请求完整路径:"+requestURL); System.out.println("请求部分路径:"+requestURI); System.out.println("请求参数:"+queryString); System.out.println("请求方式:"+method); System.out.println("协议版本号:"+protocol); System.out.println("项目站点名称:"+ contextPath); }}
测试结果:
3.5.2 获取请求参数
-
方法
方法 描述 getParameter(String name) 获取指定名称的参数 getParameterValues(String name ) 获取指定名称参数的所有值 -
示例
//获取请求参数String name = req.getParameter("name");System.out.println(name);String[] hobby = req.getParameterValues("hobby");if(hobby != null && hobby.length > 0){ //养成预先判断是否为null的好习惯 for(String h : hobby) System.out.println(h);}
测试结果:
3.5.3 请求乱码问题
由于现在的request属于接收客户端的参数,所以必然会有默认语言编码,那么在解析中文的过程中就可能会产生乱码情况,针对这种问题,有以下解决方式:
-
方式一:
req.setCharacterEncoding("UTF-8");
这种方式只针对POST请求有效(必须在接收所有数据之前设定)
-
方式二:
new String(request.getParameter(name).getBytes("ISO-8859-1"),"UTF-8");
这种方式能够解决Tomcat 7及以下版本的GET请求,也适用于POST请求,比较通用。
但是因为从Tomcat 8以后GET请求不会出现乱码,如果使用这种方式,就会将原本不是乱码的数据转成乱码。
3.5.4 请求转发
请求转发,是一种服务器行为,当客户端请求到达后,服务器进行转发,此时会将请求对象进行保存,地址栏中的URL地址不会发生改变,得到响应后,服务器端再将响应发送给客户端,从始至终只有一个请求发出。
req.getRequestDispatcher(url).forword(req,resp);
3.5.5 request作用域
通过该对象可以在一个请求中传递数据,作用范围:一次请求中有效,即服务器跳转有效。
//设置域对象内容request.setAttribute(String name, String value);//获取域对象内容request.getAttribute(String name);//删除域对象内容request.removeAttribute(String name);
3.6 HttpServletResponse对象
既然客户端发送请求,那么服务器收到请求后就需要做出相应的反应。那这个响应由谁来进行处理呢?没错,就是HttpServletResponse
。
3.6.1 响应数据
接收到客户端请求后,HttpServletResponse响应,就需要获取输出流,通过流的方式发送响应数据。
有两种方法:
- getWriter():获取字符流(只能响应回字符)
- getOutputStream():获取字节流(能响应一切数据)
注意:以上二者不能同时使用。
//字符输出流PrintWriter writer = response.getWriter();writer.write("hello");writer.write("Hello
");//字节输出流ServletOutputStream os = resp.getOutputStream();os.write("Hello".getBytes());os.write(" Hello
".getBytes());
3.6.2 响应乱码
既然请求可能会出现乱码,那么响应自然也可能会出现乱码。如果当响应内容中有中文时,在客户端就可能会显示乱码。
-
getWriter()的字符乱码
getWriter获取到的是字符流,响应中文必定会出现乱码,由于服务器端采用
ISO-8859-1
编码格式,并不支持中文。首先,解决该种乱码的方式就是在服务器端告知服务器使用一种支持中文的编码,例如UTF-8。
response.setCharacterEncoding("UTF-8");
接下来,要想正确显示,还需要指定客户端的解码方式。
response.setHeader("content-type","text/html;charset=UTF-8");
以上两步也可以通过下面方法同时设置客户端和服务器编码
response.setContentType("text/html;charset=UTF-8");
-
getOutputStream()字节乱码
由于该种方式获取到的是字节流,响应中文时,由于本身是传输字节,所以可能会乱码,也可能显示正确。如果服务器端给的字节恰好与客户端的该内容编码一致时就能正确显示,否则就会乱码。
解决方案就是让客户端和服务器端编码一致。
response.setContentType("text/html;charset=UTF-8");
3.6.3 重定向
重定向,通俗来讲可以理解为从一个页面跳转到另一个页面,在此过程中地址栏中的地址会发生变化,如果是显示页面之间的跳转,那么显示内容也会出现变化。
//重定向跳转到index.jspresponse.sendRedirect("index.jsp");
在之前还学习过请求转发,那么二者有什么区别?
请求转发 | 重定向 |
---|---|
一次请求,数据在request域中共享 | 两次请求,数据不共享 |
服务器端行为 | 客户端行为 |
地址栏不发生变化 | 地址栏发生变化 |
绝对地址定位到站点后 | 绝对地址可以写到http:// |
最后一条区别可以理解为:请求转发只能将客户端的请求在该web项目内进行转发,而重定向可以是任意可以访问的地址,例如www.baidu.com等。
3.7 Cookie对象
Cookie是浏览器提供的一种技术,将一些只在客户端使用的数据保存到本地计算机上,无需通过网络传输,因而可以提高网页处理效率,减少服务器负载,但是安全性上会出现很大问题。例如常见的记住密码就是通过Cookie实现。
Java中操作Cookie的类:javax.servlet.http.Cookie
Cookie格式:键值对用"="连接,多个键值对之间使用 ";"隔开
3.7.1 Cookie的创建和发送
Cookie创建之后需要添加到response对象中,随着response对象发送到客户端。
//创建Cookie对象Cookie cookie = new Cookie("uname","zhangsan");//发送Cookie对象response.addCookie(cookie);
在浏览器中查看Cookie:
3.7.2 Cookie的获取
使用getCookies()
方法获取客户端传回的Cookie数组,如果需要获取单个Cookie,通过getName()
获取名称,getValue()
获取Cookie值。
//获取Cookie数组Cookie[] cookies = request.getCookies();//判断数组是否为空 ----好习惯if(cookies != null && cookies.length > 0){ //遍历数组 for(Cookie cookie : cookies){System.out.println(cookie.getName()); System.out.println(cookie.getValue()); }}
获取结果:
3.7.3 Cookie设置到期时间
到期时间的取值
-
负整数
若为负数,表示不存储该Cookie。Cookie的默认值是
-1
,表示只在浏览器内存中存活,关闭窗口即消失。 -
正整数
若大于0,表示存储的秒数。当生命大于0时,浏览器会将其保存到硬盘上,直到存活时间到达才会消失。
-
零
若为0,表示删除该Cookie。无论是在浏览器内存还是在硬盘中,都会被删除。
示例:
//设置负整数 Cookie cookie = new Cookie("name2","lisi"); cookie.setMaxAge(-12); resp.addCookie(cookie); //记得响应,不然白设置了//设置正整数Cookie cookie2 = new Cookie("name2","lisi");cookie.setMaxAge(12);resp.addCookie(cookie2); //设置负整数Cookie cookie3 = new Cookie("name2","lisi");cookie.setMaxAge(0);resp.addCookie(cookie3);
3.7.4 Cookie的注意点
-
Cookie保存在当前浏览器中
目前,Cookie不能跨浏览器。
-
Cookie存中文问题
Cookie中不能出现中文,如果有中文则需要通过
URLEncoding.encode()
来进行编码,获取时通过URLDecoder.decode()
来进行解码。 -
同名Cookie问题
如果服务器发送重复的Cookie,则会覆盖掉原来的Cookie。
-
浏览器存放Cookie的数量
不同浏览器对Cookie的限制也是不同的,但是都是有上限的。Cookie一般由服务器端创建和设定,后期结合Session来实现回话跟踪。
3.7.5 Cookie的路径
Cookie的setPath()设置cookie的路径,这个路径直接决定服务器的请求是否会从浏览器中加载某些Cookie。
-
当前服务器下任何项目的任何资源都可以获取Cookie对象
cookie.setPath("/");
-
当前项目下的资源可获取Cookie对象(默认不设置的情况)
//假设当前项目为:s01cookie.setPath("/s01");
-
指定项目下的资源可以获取Cookie对象
//当前项目为s01,设置so2项目可以获取该cookiecookie.setPath("/s02");
-
指定目录下的资源可以获取Cookie对象
//指定s01项目下的cook目录可以获取该Cookiecookie.setPath("/s01/cook")
3.8 HttpSession对象
HttpSession是一个纯粹的接口,并没有父类。这是因为session本身就属于HTTP协议的范畴。
对服务器而言,每一个连接到它的客户端都是一个session,servlet容器会使用此接口创建HTTP客户端与服务器之间的回话。session对于客户端和服务器都是可感知的,每一个session只保存在当前浏览器中,并在相应的页面获取。
session的所用就是标识一次回话。并且在一次回话期间共享数据,可以通过request.getSession()来获取Session对象。
//获取Session对象,存在就获取,不存在就创建HttpSession session = req.getSession();//获取session标识String id = session.getId();//获取session创建时间session.getCreationTime();//获取最后一次访问时间session.getLastAccessedTime();//判断是否是一个新的Session对象session.isNew();
3.8.1 标识符JSESSIONID
JSESSIONID用来标识一个会话(session),能够确保会话的唯一性。
每当一次请求到达服务器,如果开启了会话,服务器第一步就会查看是否从客户端传来了一个名为JSESSIONID的Cookie,如果没有则表示这是一次新的会话,从而创建一个新的Session对象。如果不是新的会话,则会将JSESSIONID这个Cookie回传,然后根据这个唯一id查找对应Session对象。
这里所提到的JSESSIONID是一个比较特殊的Cookie。当用户请求服务器时,如果访问了session,那么服务器就会创建一个名为JSESSIONID,值为被访问的sessionId 的Cookie对象。
因此,Session的底层依赖Cookie实现。
3.8.2 Session域对象
session是一次会话,在一次会话期间数据是可以共享的。
//获取session对象HttpSession session = request.getSession();//设置session域对象session.setAttribute("name","admin");//获取指定域对象String name = (String)request.getAttribute("name");//移除指定名称的session对象session.removeAttribute("name");
3.8.3 Session对象的销毁
-
默认时间到期
第一次操作session时,会创建session对象,Tomcat默认时间是30min,如果再操作的话,session会重新计时。
可以在Tomcat安装路径的conf目录下的web.xml文件中对默认时间进行修改(不推荐):
<session-config><session-timeout>30</session-timeout></session-config>
-
自己设定到期时间
除了在配置文件中设置到期时间,还可以通过
session.setMaxInactiveInterval(int time)
来设置最大不活动时间(其实就是存活时间),单位:秒。HttpSession session = request.getSession();//设置最大不活动时间session.setMaxInactiveInterval(15); //15秒
获取最大不活动时间:
getMaxInactiveInterval()
session.getMaxInactiveInterval(15); //15秒
-
立刻失效
//立刻销毁session对象session.invalidate();
-
关闭浏览器
前面讲过,Session的底层依赖Cookie实现,因此关闭浏览器之后,session也就失效了。
-
关闭服务器
关闭服务器时,session销毁,也意味着此次会话结束,数据共享结束。
3.9 ServletContext对象
每一个web应用有且仅有一个ServletContext对象,又称为Application对象。每创建一个web应用就会产生一个对应的ServletContext对象。
ServletContext对象的两大作用:为整个应用程序共享数据 和 保存当前应用程序相关的信息。
3.9.1 ServletContext对象的获取
-
通过request对象获取
ServletContext servletContext = request.getServletContext();
-
通过session对象获取
ServletContext servletContext = request.getSession().getServletContext();
-
通过ServletConfig对象获取
ServletConfig servletConfig = getServletConfig();ServletContext servletConetxt = servletConfig.getServletConetext();
-
直接获取
ServletContext servletContext = getServletContext();
常用方法:
getServerInfo() | 获取当前服务器的版本信息 |
---|---|
getRealPath() | 获取项目的真实路径 |
3.10 文件上传和下载
上网的时候经常会遇到上传或者下载文件,那servlet如何实现文件上传和下载?
3.10.1 文件上传
-
前台页面
文件上传时通常都会有一个上传文件界面,首先我们需要一个表单,请求方式为POST;接下来,form表单的enctype必须设置为"multipart/form-data",即enctype=“multipart/form-data”,表示设置表单类型为文件上传表单。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>文件上传</title></head><body> <form method="post" enctype="multipart/form-data" action="uploadServlet"> 姓名:<input type="text" name="uname"> <br> 文件:<input type="file" name="myfile"><br> <button>提交</button> </form></body></html>
-
后台代码
使用注解
@MultipartConfig
将一个Servlet标识为支持文件上传。之后Servlet会将multipart/form-data的POST请求封装成Part,通过Part对上传的文件操作。package com.zs.servlet;import javax.servlet.ServletException;import javax.servlet.annotation.MultipartConfig;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.Part;import java.io.IOException;@WebServlet("/uploadServlet")@MultipartConfig //支持文件上传,必须要加该注解!!!public class UploadServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("文件上传..."); //先设置编码格式 request.setCharacterEncoding("UTF-8"); //获取普通表单项 String name = request.getParameter("uname"); System.out.println("名字:"+name); //上传文件 Part part = request.getPart("myfile"); //获取Part对象 String fileName = part.getSubmittedFileName(); //获取文件名 System.out.println("上传文件名" + fileName); String filePath = request.getServletContext().getRealPath("/"); System.out.println("文件存放路径:" + filePath); part.write(filePath + "/" + fileName); //将上传文件放到指定位置 }}
3.10.2 文件下载
文件下载,就是将服务器资源拷贝到本地的过程。可以通过两种方式实现下载:超链接下载 和 通过代码下载。
准备一个download文件夹:
将该文件夹部署到Tomcat服务器,否则无法访问到
-
超链接下载
当超链接遇到浏览器不识别的资源时会自动下载;
<a href="test.zip">超链接下载</a>
也可以通过download属性实现下载,但部分浏览器不支持。
<a href="test.txt" download>超链接下载</a>
-
通过后台代码实现下载
实现步骤:
首先,通过response.setContentType方法设置Content-type头字段的值,为浏览器无法使用某种方式或者激活某个程序来处理的MIME类型,例如"application/octet-stream"或"application/x-msdownload"等。
**其次,**需要通过response.setHeader方法设置Content-Disposition头的值为"attachment;filename=文件名"
最后,读取下载文件,调用response.getOutputStream方法向客户端写入附件内容。
package com.zs.servlet;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;@WebServlet("/downloadServlet")public class DownloadServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("文件下载......"); //设置请求的编码格式 request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); //获取参数 取得文件名 String fileName = request.getParameter("fileName"); if(fileName == null || "".equals(fileName.trim())){ response.getWriter().write("请输入要下载的文件名!"); response.getWriter().close(); return; } //得到文件存放路径 String filePath = request.getServletContext().getRealPath("/download/"); //通过路径得到File对象 File file = new File(filePath + fileName); //判断文件对象是否存在,并且是一个标准文件 if(file.exists() && file.isFile()){ //设置响应类型 response.setContentType("application/x-msdownload"); //设置响应头 response.setHeader("Content-Disposition","attachment;filename="+fileName); //输入流---读文件 InputStream is = new FileInputStream(file); //输出流 ServletOutputStream os = response.getOutputStream(); //定义数组 byte[] bytes = new byte[1024]; int len = 0; while((len = is.read(bytes)) != -1){ os.write(bytes,0,len); } //关闭资源 os.close(); is.close(); }else{ response.getWriter().write("文件不存在,请重新输入!"); response.getWriter().close(); } }}
创作打卡挑战赛 赢取流量/现金/CSDN周边激励大奖