9 Ajax 研究
9.1 简介
- AJAX = Asynchronous JavaScript an XML (异步的 JavaScript 和 XML)
- AJAX 是一种无需重新加载整个网页的情况下,能够更新部分网页的技术。
- Ajax 不是一种新的编程语言,而是一种用于创建更快以及交互性更强的Web应用程序的技术
- 在2005年,Google 通过其 Google Suggest 使AJAX变得流行起来。Google Suggest能够自动帮你完成搜索单词。
- Google Suggest 使用AJAX创造出动态性极强的Web界面:当你在谷歌的搜索栏狂输入关键字时,JavaScript会把这些字符发送到服务器,然后服务器会返回一个搜索建议的列表。
- 就和国内百度的搜索框一样!
- 传统的网页技术(即不用Ajax技术的网页),想要更新内容或者提交一个表单,都需要从新加载整个网页。
- 使用Ajax技术的网页,通过在后台服务器进行少量的数据交换,就可以实现异步局部更新。
- 使用Ajax,用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的Web用户界面。
9.2 伪造Ajax
可以使用前端的一个标签来哦伪造一个ajax的样子,体验页面无刷新的样子。iframe标签。
-
新建一个module:springmvc-06-ajax,导入web支持!
-
完善基础架构
配置web.xml:
<!--1.注册servlet--> <servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--通过初始化参数指定SpringMVC配置文件的位置,进行关联--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param> <!--启动顺序,数字越小,启动越早--> <load-on-startup>1</load-on-startup> </servlet> <!--配置拦截哪些请求--> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--添加过滤器解决乱码问题--> <filter> <filter-name>encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/</url-pattern> </filter-mapping>
applicationContext.xml
<!--自动扫描指定的包,下面所有注解类交给IOC容器管理--> <context:component-scan base-package="com.serene.controller"/> <!--视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp" /> </bean> <!--消息转换配置,解决乱码问题--> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8"/> </bean> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"> <property name="failOnEmptyBeans" value="false"/> </bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
请求相应方法:
package com.serene.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class AjaxController { @RequestMapping("/t1") public String test(){ return "hello,ajax !"; } }
配置Tomcat,测试
-
WEB-INF目录下编写一个test.html 使用iframe测试,感受下效果!
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>serene 伪造Ajax体验</title> </head> <body> <script type="text/javascript"> window.onload = function(){ var myDate = new Date(); document.getElementById('currentTime').innerText = myDate.getTime(); }; function LoadPage(){ var targetUrl = document.getElementById('url').value; console.log(targetUrl); document.getElementById("iframePosition").src = targetUrl; } </script> <div> <p>请输入要加载的地址:<span id="currentTime"></span></p> <p> <input id="url" type="text" value="https://www.baidu.com/"/> <input type="button" value="提交" onclick="LoadPage()"> </p> </div> <div> <h3>加载页面位置:</h3> <iframe id="iframePosition" style="width: 100%;height: 500px;"></iframe> </div> </body> </html>
-
使用IDEA打开浏览器测试
利用Ajax可以做:
- 注册时,输入用户名自动监测用户是否已经存在。
- 登录时,提示用户密码错误
- 删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行也删除。
- …等等
9.3 jQuery.ajax
纯JS原生实现Ajax这里不去讲解,直接使用jQuery提供的,方便学习和使用,避免重复造轮子,有兴趣的同学可以去了解下JS原生XMLHttpRequest!
Ajax的核心是XMLHttpRequest对象(XHR)。XHR为向服务器发送请求和解析服务器响应提供了接口。能够以异步方式从服务器获取新数据。
jQuery 提供多个与AJAX有关的方法。
通过jQuery AJAX方法,能够视同HTTP Get 和 HTTP Post 从远程服务器上请求文本、HTML、XML会JSON-同时能够把这些外部数据直接载入网页的被选中元素中。
jQuery不是生产者,而是大自然的搬运工。
jQuery Ajax 本质就是XMLHTTPRequest,对它进行了封装,方便调用!
jQuery.ajax(...)
部分参数:
url:请求地址
type:请求方式,GET、POST(1.9.0之后用method)
headers:请求头
data:要发送的数据
contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")
async:是否异步
timeout:设置请求超时时间(毫秒)
beforeSend:发送请求前执行的函数(全局)
complete:完成之后执行的回调函数(全局)
success:成功之后执行的回调函数(全局)
error:失败之后执行的回调函数(全局)
accepts:通过请求头发送给服务器,告诉服务器当前客户端可接受的数据类型
dataType:将服务器端返回的数据转换成指定类型
"xml": 将服务器端返回的内容转换成xml格式
"text": 将服务器端返回的内容转换成普通文本格式
"html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。
"script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式
"json": 将服务器端返回的内容转换成相应的JavaScript对象
"jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数
做一个简单的测试,使用最原始的 HttpServletResponse处理,最简单,最通用
-
springmvc配置文件中需要导入静态资源过滤,后面会手动导入jQuery
<!--使用jQuery需要配置,静态资源过滤--> <mvc:default-servlet-handler />
-
下载jQuery资源,创建/web/static/js目录,手动导入项目中
下载资源方法:直接搜索jQuery,进入官网,点击下载,右键另存为。
-
编写一个 AjaxController
@RequestMapping("/a1") public void ajax1(String name, HttpServletResponse response) throws IOException { if("serene".equals(name)){ response.getWriter().print("true"); System.out.println("***true***"); }else { response.getWriter().print("false"); System.out.println("***false***"); } }
-
编写 index.jsp
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2021/7/7 0007 Time: 22:39 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$ jQuery.ajax $</title> <%--手动导入jQuery --%> <script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script> <%--也可以下载导入jQuery <script src="https://code.jquery.com/jquery-3.6.0.js"></script>--%> <script> function a1(){ $.post({ url:"${pageContext.request.contextPath}/a1", data:{'name':$("#txtName").val()}, success:function (data,status) { alert(data); alert(status); } }); } </script> </head> <body> <%--onblur:失去焦点触发事件--%> 用户名:<input type="text" id="txtName" οnblur="a1()"/> </body> </html>
-
启动Tomcat测试!打开浏览器的控制台,当鼠标离开输入框的时候,可以看到发出了一个ajax的请求!是后台返回给我们的结果!测试成功
SpringMVC实现
- 实体类User
package com.serene.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private int age;
private String sex;
}
- 请求获取一个集合对象,展示到前端页面
@RequestMapping("/a2")
public List<User> ajax2(){
List<User> list = new ArrayList<User>();
list.add(new User("韵宝宝1", 1, "男"));
list.add(new User("韵宝宝2", 2, "男"));
list.add(new User("韵宝宝3", 3, "男"));
return list;//由于@RestController 注解,将list转成json格式返回
}
- 前端页面 ajax-test2.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2021/7/7 0007
Time: 22:39
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$ jQuery.ajax2 $</title>
<%--手动导入jQuery --%>
<script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script>
<script>
$(function () {
$("#btn").click(function () {
/*
$.post(url, param[可以省略], success)
*/
$.post("${pageContext.request.contextPath}/a2",function (data) {
console.log(data)
var html="";
for (var i = 0; i <data.length ; i++) {
html+= "<tr>" +
"<td>" + data[i].name + "</td>" +
"<td>" + data[i].age + "</td>" +
"<td>" + data[i].sex + "</td>" +
"</tr>"
}
$("#content").html(html);
});
})
})
</script>
</head>
<body>
<input type="button" id="btn" value="获取数据"/>
<table width="80%" align="center">
<tr>
<td>姓名</td>
<td>年龄</td>
<td>性别</td>
</tr>
<tbody id="content">
</tbody>
</table>
</body>
</html>
- 测试数据成功回显
9.4 注册效果提示
在测试一个Demo,思考下平时注册的时候,输入框后面的实时提示是怎么做到的,如何优化。
-
写一个Controller
@RequestMapping("/a3") public String ajax3(String name, String pwd){ String msg=""; //这里模拟一个数据库中存在的数据 serene;666666 if(null != name){ if(name.equals("serene")){ msg = "OK"; }else { msg = "name input error 错误!"; } } if (pwd!=null){ if ("666666".equals(pwd)){ msg = "OK"; }else { msg = "pwd input error 错误!"; } } return msg; }
-
前端页面 login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登录页面 ajax3</title> <script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script> <script> function a1(){ $.post({ url:"${pageContext.request.contextPath}/a3", data:{'name':$("#name").val()}, success:function (data) { if (data.toString()=='OK'){ $("#userInfo").css("color","green"); }else { $("#userInfo").css("color","red"); } $("#userInfo").html(data); } }); } function a2(){ $.post({ url:"${pageContext.request.contextPath}/a3", data:{'pwd':$("#pwd").val()}, success:function (data) { if (data.toString()=='OK'){ $("#pwdInfo").css("color","green"); }else { $("#pwdInfo").css("color","red"); } $("#pwdInfo").html(data); } }); } </script> </head> <body> <p> 用户名:<input type="text" id="name" οnblur="a1()"/> <span id="userInfo"></span> </p> <p> 密码:<input type="text" id="pwd" οnblur="a2()"/> <span id="pwdInfo"></span> </p> </body> </html>
-
测试效果:鼠标离开文本输入框焦点时,动态相应请求,会完成一次局部刷新!【这里信息带中文,记得处理 json 乱码问题】
正确的用户或者密码会显示 绿色的OK,错误会显示 红色的错误提示!
对应代码:springmvc-06-ajax
10 拦截器
10.1 概述
SpringMVC的处理拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自定义一些拦截器来实现特定的功能。
过滤器和拦截器的区别:拦截器是AOP思想的具体应用。
过滤器:
- servlet规范中的一部分,任何java web工程都可以使用
- 在 url-pattern 中配置了 /* 自后,可以对所有要访问的资源进行拦截
拦截器:
- 拦截器是SpringMVC框架自己的,只有使用SpringMVC框架的工程才可以使用
- 拦截器只会拦截访问的控制器方法,如果访问的是 jsp\html\css\image\js是不会进行拦截的
10.2 自定义拦截器
如何实现自定义拦截器?
想要自定义拦截器,必须实现 HandlerInterceptor 接口。
-
新建一个Module,springmvc-07-Interceptor,添加web支持
-
配置web.xml 和 applicationContext.xml。确定lib库导入
-
编写一个拦截器
package com.serene.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyInterceptor implements HandlerInterceptor { //在请求处理方法之前执行 //如果返回 true 执行下一个拦截器 //如果返回 false 就不执行下一个拦截器 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("********处理前!**********"); return true; } //在请求处理方法执行之后执行 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("********处理后!************"); } //在dispatcherServlet处理后执行,做清理工作. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("***********清理!************"); } }
-
在springmvc配置文件中配置拦截器
<!--关于拦截器的配置--> <mvc:interceptors> <mvc:interceptor> <!--/** 包括路径及其子路径--> <!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截--> <!--/admin/** 拦截的是/admin/下的所有--> <mvc:mapping path="/**"/> <!--bean配置的就是拦截器--> <bean class="com.serene.interceptor.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors>
-
编写一个Controller,接收请求
@Controller public class InterceptorController { @RequestMapping("/inct") @ResponseBody public String testFunction() { System.out.println("控制器中的方法执行了"); return "hello"; } }
-
前端测试请求 index.jsp
<a href="${pageContext.request.contextPath}/inct">拦截器测试</a>
-
启动Tomcat,测试!
可以看到,在发生请求的时候,控制器处理请求前会先经过拦截器,然后再处理请求。
10.3 验证用户是否登录(认证用户)
实现思路
-
有一个登陆页面,需要写一个controller访问页面。
-
登陆页面优异提交表单的动作。需要controller中处理。判断用户名密码是否正确。如果正确,向session中写如用户信息。返回登陆成功页面。
-
拦截用户请求,判断用户是否登录。如果用户已经登陆,放行。如果用户未登录,跳转到登录页面。
测试:
-
编写一个登录页面 /WEB-INF/jsp/login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <h1> 登录页面 </h1> <hr> <body> <form action="${pageContext.request.contextPath}/user/login"> 用户名:<input type="text" name="username"> <br> 密码:<input type="password" name="pwd"> <br> <input type="submit" value="提交"> </form> </body> </html>
-
编写一个Controller处理请求
@Controller @RequestMapping("/user") public class UserController { //跳转到登陆页面 @RequestMapping("/jumplogin") public String jumpLogin() throws Exception { return "login"; } //跳转到成功页面 @RequestMapping("/jumpSuccess") public String jumpSuccess() throws Exception { return "success"; } //登陆提交 @RequestMapping("/login") public String login(HttpSession session, String username, String pwd) throws Exception { // 向session记录用户身份信息 System.out.println("接收前端==="+username); session.setAttribute("user", username); return "success"; } //退出登陆 @RequestMapping("logout") public String logout(HttpSession session) throws Exception { // session 过期 session.invalidate(); return "login"; } }
-
编写一个登录成功的页面 /WEB-INF/jsp/success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1> 登录成功页面 </h1> <hr> ${user} <a href="${pageContext.request.contextPath}/user/logout">注销</a> </body> </html>
-
在 index.jsp 页面测试跳转!启动Tomcat测试,未登录也可以进入主页!
<%--登录--%> <a href="${pageContext.request.contextPath}/user/jumplogin">登录</a> <a href="${pageContext.request.contextPath}/user/jumpSuccess">成功页面</a>
-
编写用户登录拦截器
package com.serene.interceptor; public class UserInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException, ServletException, IOException { // 如果是登陆页面则放行 System.out.println("uri: " + request.getRequestURI()); if (request.getRequestURI().contains("login")) { return true; } HttpSession session = request.getSession(); // 如果用户已登陆也放行 if(session.getAttribute("user") != null) { return true; } // 用户没有登陆跳转到登陆页面 request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response); System.out.println("******用户没有登录!*********"); return false; } public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { System.out.println("*********处理后!***********"); } public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { System.out.println("***********清理!************"); } }
-
在springmvc配置文件中注册拦截器
<!--关于拦截器的配置--> <mvc:interceptors> <mvc:interceptor> <!--/** 包括路径及其子路径--> <!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截--> <!--/admin/** 拦截的是/admin/下的所有--> <mvc:mapping path="/**"/> <!--bean配置的就是拦截器--> <!--<bean class="com.serene.interceptor.MyInterceptor"/>--> <bean class="com.serene.interceptor.UserInterceptor"/> </mvc:interceptor> </mvc:interceptors>
-
再次启动Tomcat测试,得到我们想要的拦截效果!
对应代码:springmvc-07-Interceptor
11 文件上传和下载
11.1 准备工作
文件上传是项目开发中最常见的功能之一,SpringMVC 可以很好的支持的支持文件上传牡丹石SpringMVC 山西该文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。
前端表单要求:为了能上传文件,必须将表单的method 设置为POST,并将enctype设置为 multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器。
对表单中的 enctype 属性做个详细的说明:
- application/x-www=form-urlencoded:默认方式,只处理表单域中的value 属性值,采用这种编码方式的表单会将会将表单域中的值处理成URL编码方式。
- multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
- text/plain:除了把空格转换为 “+” 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。
<form action="" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit">
</form>
一旦设置了 enctype 为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务端解析原始的HTTP相应。在2003年,Apache Software Foundation 发布了开源的Commons FileUpload组件,其很快成为Servlet/JSP程序员上传文件的最佳选择。
- Servlet3.0规范已经提供方法来处理文件上传,但这种上传需要在Servlet中完成。
- 而SpringMVC则提供了更简单的封装。
- SpringMVC为文件上传提供了直接的支持,这种支持是与即插即用的MultipartResolver实现的。
- SpringMVC 使用Apache Commons FileUpload技术实现了一个MultipartResolver实现de .
- CommonsMultipartResolver。因此,SpringMVC 的文件上传还需要依赖Apache Commons FileUpload的组件
11.2 文件上传
-
导入文件上传的jar包,commons-fileupload,Maven会自动帮忙导入它的依赖包 commons-io包。
<dependencies> <!--文件上传--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency> <!--servlet-api 导入高版本的--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> </dependencies>
-
配置bean:multipartResolver
【注意】!!!这个bean的id必须为:multipartResolver,否则上传文件会报404的错误!!
<!--文件上传配置--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 --> <property name="defaultEncoding" value="utf-8"/> <!-- 上传文件大小上限,单位为字节(10485760=10M) --> <property name="maxUploadSize" value="10485760"/> <property name="maxInMemorySize" value="40960"/> </bean>
CommonsMultipartFile 的常用方法:
- String getOriginalFilename():获取上传文件的原名
- InputStream getInputStream():获取文件流
- void transferTo(File dest):将上传文件保存到一个目录中
-
编写前端页面
<form action="/upload" enctype="multipart/form-data" method="post"> <input type="file" name="file"/> <input type="submit" value="upload"> </form>
-
Controller
@Controller public class FileController { //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象 //批量上传CommonsMultipartFile则为数组即可 @RequestMapping("/upload") public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException { //获取文件名 : file.getOriginalFilename(); String uploadFileName = file.getOriginalFilename(); //如果文件名为空,直接回到首页! if ("".equals(uploadFileName)){ System.out.println("上传文件名为空!"); return "redirect:/index.jsp"; } System.out.println("上传文件名 : "+uploadFileName); //上传路径保存设置 String path = request.getServletContext().getRealPath("/upload"); //如果路径不存在,创建一个 File realPath = new File(path); if (!realPath.exists()){ realPath.mkdir(); } System.out.println("上传文件保存地址:"+realPath); InputStream is = file.getInputStream(); //文件输入流 OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流 //读取写出 int len=0; byte[] buffer = new byte[1024]; while ((len=is.read(buffer))!=-1){ os.write(buffer,0,len); os.flush(); } os.close(); is.close(); return "redirect:/index.jsp"; } }
-
测试上传文件,OK!
采用file.Transto 来保存上传的文件
-
编写Controller
/* * 采用file.Transto 来保存上传的文件 */ @RequestMapping("/upload2") public String fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException { //上传路径保存设置 String path = request.getServletContext().getRealPath("/upload"); File realPath = new File(path); if (!realPath.exists()){ realPath.mkdir(); } //上传文件地址 System.out.println("上传文件保存地址:"+realPath); //通过CommonsMultipartFile的方法直接写文件(注意这个时候) file.transferTo(new File(realPath +"/"+ file.getOriginalFilename())); return "redirect:/index.jsp"; }
-
前端提交表单修改
<form action="${pageContext.request.contextPath}/upload2" enctype="multipart/form-data" method="post"> <input type="file" name="file"/> <input type="submit" value="upload2"> </form>
-
访问提交测试,OK!
11. 3 文件下载
文件下载步骤:
1、设置response的响应投
2、读取文件 --InputStream
3、写出文件 --OutputStream
4、执行操作
5、关闭流(先开后关)
代码实现
Controller
//文件下载
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
//要下载的图片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = "healer.jpeg";
//1、设置response 响应头
response.reset(); //设置页面不缓存,清空buffer
response.setCharacterEncoding("UTF-8"); //字符编码
response.setContentType("multipart/form-data"); //二进制传输数据
//设置响应头
response.setHeader("Content-Disposition",
"attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));
File file = new File(path,fileName);
//2、 读取文件--输入流
InputStream input=new FileInputStream(file);
//3、 写出文件--输出流
OutputStream out = response.getOutputStream();
byte[] buff =new byte[1024];
int index=0;
//4、执行 写出操作
while((index= input.read(buff))!= -1){
out.write(buff, 0, index);
out.flush();
}
out.close();
input.close();
return null;
}
前端
<a href="/download">点击下载</a>
测试,文件下载OK,可以对比之前学习的JavaWeb原生上传下载的方式,既可以知道这个便捷多了!
参考笔记:https://blog.csdn.net/xiangminlu/article/details/105680357
对应代码:springmvc-08-file