Ajax

简介

  • AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
  • AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
  • Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。
  • 在 2005 年,Google 通过其 Google Suggest 使 AJAX 变得流行起来。Google Suggest能够自动帮你完成搜索单词。
  • Google Suggest 使用 AJAX 创造出动态性极强的 web 界面:当您在谷歌的搜索框输入关键字时,JavaScript 会把这些字符发送到服务器,然后服务器会返回一个搜索建议的列表。
  • 就和国内百度的搜索框一样!
  • 传统的网页(即不用ajax技术的网页),想要更新内容或者提交一个表单,都需要重新加载整个网页。
  • 使用ajax技术的网页,通过在后台服务器进行少量的数据交换,就可以实现异步局部更新。
  • 使用Ajax,用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的Web用户界面。

伪造Ajax

我们可以使用前端的一个标签来伪造一个ajax的样子。iframe标签

1、新建一个module :springmvc-06-ajax , 导入web支持!

2、编写一个 ajax-frame.html 使用 iframe 测试,感受下效果

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Ajax初体验</title>
  6. </head>
  7. <body>
  8. <script type="text/javascript">
  9. window.onload = function(){
  10. var myDate = new Date();
  11. document.getElementById('currentTime').innerText = myDate.getTime();
  12. };
  13. function LoadPage(){
  14. var targetUrl = document.getElementById('url').value;
  15. console.log(targetUrl);
  16. document.getElementById("iframePosition").src = targetUrl;
  17. }
  18. </script>
  19. <div>
  20. <p>请输入要加载的地址:<span id="currentTime"></span></p>
  21. <p>
  22. <input id="url" type="text" value="https://www.bilibili.com/"/>
  23. <input type="button" value="提交" onclick="LoadPage()">
  24. </p>
  25. </div>
  26. <div>
  27. <h3>加载页面位置:</h3>
  28. <iframe id="iframePosition" style="width: 100%;height: 500px;"></iframe>
  29. </div>
  30. </body>
  31. </html>

3、使用IDEA开浏览器测试一下!

利用AJAX可以做:

  • 注册时,输入用户名自动检测用户是否已经存在。
  • 登陆时,提示用户名密码错误
  • 删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行也删除。

jQuery.ajax.

Ajax的核心是XMLHttpRequest对象(XHR)。XHR为向服务器发送请求和解析服务器响应提供了接口。能够以异步方式从服务器获取新数据。

jQuery 提供多个与 AJAX 有关的方法。

通过 jQuery AJAX 方法,您能够使用 HTTP Get 和 HTTP Post 从远程服务器上请求文本、HTML、XML 或 JSON – 同时您能够把这些外部数据直接载入网页的被选元素中。

jQuery 不是生产者,而是大自然搬运工。

jQuery Ajax本质就是 XMLHttpRequest,对他进行了封装,方便调用!

  1. jQuery.ajax(...)
  2. 部分参数:
  3. url:请求地址
  4. type:请求方式,GETPOST1.9.0之后用method
  5. headers:请求头
  6. data:要发送的数据
  7. contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")
  8. async:是否异步
  9. timeout:设置请求超时时间(毫秒)
  10. beforeSend:发送请求前执行的函数(全局)
  11. complete:完成之后执行的回调函数(全局)
  12. success:成功之后执行的回调函数(全局)
  13. error:失败之后执行的回调函数(全局)
  14. accepts:通过请求头发送给服务器,告诉服务器当前客户端可接受的数据类型
  15. dataType:将服务器端返回的数据转换成指定类型
  16. "xml": 将服务器端返回的内容转换成xml格式
  17. "text": 将服务器端返回的内容转换成普通文本格式
  18. "html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。
  19. "script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式
  20. "json": 将服务器端返回的内容转换成相应的JavaScript对象
  21. "jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数

先来个简单的测试,使用最原始的HttpServletResponse处理 , 最简单 , 最通用

1、配置web.xml 和 springmvc的配置文件【记得静态资源过滤和注解驱动配置上

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:mvc="http://www.springframework.org/schema/mvc"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/context
  9. https://www.springframework.org/schema/context/spring-context.xsd
  10. http://www.springframework.org/schema/mvc
  11. https://www.springframework.org/schema/mvc/spring-mvc.xsd">
  12. <!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
  13. <context:component-scan base-package="com.kuang.controller"/>
  14. <!--静态资源过滤-->
  15. <mvc:default-servlet-handler />
  16. <mvc:annotation-driven />
  17. <!-- 视图解析器 -->
  18. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
  19. id="internalResourceViewResolver">
  20. <!-- 前缀 -->
  21. <property name="prefix" value="/WEB-INF/jsp/" />
  22. <!-- 后缀 -->
  23. <property name="suffix" value=".jsp" />
  24. </bean>
  25. </beans>

2、编写一个AjaxController

  1. @Controller
  2. public class AjaxController {
  3. @RequestMapping("/a1")
  4. public void ajax1(String name , HttpServletResponse response) throws IOException {
  5. System.out.println("a1:parm-->" + name);
  6. if ("admin".equals(name)){
  7. response.getWriter().print("true");
  8. }else{
  9. response.getWriter().print("false");
  10. }
  11. }
  12. }

3、导入jquery , 可以使用在线的CDN , 也可以下载导入

  1. <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  2. <script src="${pageContext.request.contextPath}/statics/js/jquery-3.3.1.min.js"></script>

4、编写index.jsp测试

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>$Title$</title>
  5. <script src="${pageContext.request.contextPath}/static/jquery-3.3.1.min.js"></script>
  6. <script>
  7. function a1(){
  8. $.post({
  9. url:"${pageContext.request.contextPath}/a1",
  10. data:{'name':$("#username").val()},
  11. success:function (data) {
  12. alert(data);
  13. }
  14. });
  15. }
  16. </script>
  17. </head>
  18. <body>
  19. <%--onblur:失去焦点触发事件--%>
  20. 用户名:<input type="text" id="username" onblur="a1()"/>
  21. </body>
  22. </html>

5、启动tomcat测试!打开浏览器的控制台,当我们鼠标离开输入框的时候,可以看到发出了一个ajax的请求!是后台返回给我们的结果!测试成功!

Springmvc实现

实体类user

  1. public class User {
  2. private String name;
  3. private int age;
  4. private String sex;
  5. /*
  6. get,set,toString
  7. */
  8. }

我们来获取一个集合对象,展示到前端页面[记得导入json依赖不然会500]

  1. <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
  2. <dependency>
  3. <groupId>com.fasterxml.jackson.core</groupId>
  4. <artifactId>jackson-databind</artifactId>
  5. <version>2.9.8</version>
  6. </dependency>
  1. @RestController
  2. public class AjaxController {
  3. @RequestMapping("/a2")
  4. public List<User> ajax2(){
  5. List<User> list = new ArrayList<User>();
  6. list.add(new User("张三",16,"男"));
  7. list.add(new User("李四",17,"男"));
  8. list.add(new User("王五",18,"男"));
  9. return list; //由于@RestController注解,将list转成json格式返回
  10. }
  11. }

前端页面

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. <input type="button" id="btn" value="获取数据"/>
  8. <table width="80%" align="center">
  9. <tr>
  10. <td>姓名</td>
  11. <td>年龄</td>
  12. <td>性别</td>
  13. </tr>
  14. <tbody id="content">
  15. </tbody>
  16. </table>
  17. <script src="${pageContext.request.contextPath}/static/jquery-3.3.1.min.js"></script>
  18. <script>
  19. $(function () {
  20. $("#btn").click(function () {
  21. $.post("${pageContext.request.contextPath}/a2",function (data) {
  22. console.log(data)
  23. var html="";
  24. for (var i = 0; i <data.length ; i++) {
  25. html+= "<tr>" +
  26. "<td>" + data[i].name + "</td>" +
  27. "<td>" + data[i].age + "</td>" +
  28. "<td>" + data[i].sex + "</td>" +
  29. "</tr>"
  30. }
  31. $("#content").html(html);
  32. });
  33. })
  34. })
  35. </script>
  36. </body>
  37. </html>

成功实现了数据回显!可以体会一下Ajax的好处!

注册提示效果

我们再测试一个小Demo,思考一下我们平时注册时候,输入框后面的实时提示怎么做到的;如何优化

我们写一个Controller

  1. @RestController
  2. public class AjaxController {
  3. @RequestMapping("/a3")
  4. public String ajax3(String name,String pwd){
  5. String msg = "";
  6. //模拟数据库中存在数据
  7. if (name!=null){
  8. if ("admin".equals(name)){
  9. msg = "OK";
  10. }else {
  11. msg = "用户名输入错误";
  12. }
  13. }
  14. if (pwd!=null){
  15. if ("123456".equals(pwd)){
  16. msg = "OK";
  17. }else {
  18. msg = "密码输入有误";
  19. }
  20. }
  21. return msg; //由于@RestController注解,将msg转成json格式返回
  22. }
  23. }

前端页面 login.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>ajax</title>
  5. <script src="${pageContext.request.contextPath}/static/jquery-3.3.1.min.js"></script>
  6. <script>
  7. function a1(){
  8. $.post({
  9. url:"${pageContext.request.contextPath}/a3",
  10. data:{'name':$("#name").val()},
  11. success:function (data) {
  12. if (data.toString()=='OK'){
  13. $("#userInfo").css("color","green");
  14. }else {
  15. $("#userInfo").css("color","red");
  16. }
  17. $("#userInfo").html(data);
  18. }
  19. });
  20. }
  21. function a2(){
  22. $.post({
  23. url:"${pageContext.request.contextPath}/a3",
  24. data:{'pwd':$("#pwd").val()},
  25. success:function (data) {
  26. if (data.toString()=='OK'){
  27. $("#pwdInfo").css("color","green");
  28. }else {
  29. $("#pwdInfo").css("color","red");
  30. }
  31. $("#pwdInfo").html(data);
  32. }
  33. });
  34. }
  35. </script>
  36. </head>
  37. <body>
  38. <p>
  39. 用户名:<input type="text" id="name" onblur="a1()"/>
  40. <span id="userInfo"></span>
  41. </p>
  42. <p>
  43. 密码:<input type="text" id="pwd" onblur="a2()"/>
  44. <span id="pwdInfo"></span>
  45. </p>
  46. </body>
  47. </html>

【记得处理json乱码问题】

测试一下效果,动态请求响应,局部刷新,就是如此!

获取baidu接口Demo

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5. <title>JSONP百度搜索</title>
  6. <style>
  7. #q{
  8. width: 500px;
  9. height: 30px;
  10. border:1px solid #ddd;
  11. line-height: 30px;
  12. display: block;
  13. margin: 0 auto;
  14. padding: 0 10px;
  15. font-size: 14px;
  16. }
  17. #ul{
  18. width: 520px;
  19. list-style: none;
  20. margin: 0 auto;
  21. padding: 0;
  22. border:1px solid #ddd;
  23. margin-top: -1px;
  24. display: none;
  25. }
  26. #ul li{
  27. line-height: 30px;
  28. padding: 0 10px;
  29. }
  30. #ul li:hover{
  31. background-color: #f60;
  32. color: #fff;
  33. }
  34. </style>
  35. <script>
  36. // 2.步骤二
  37. // 定义demo函数 (分析接口、数据)
  38. function demo(data){
  39. var Ul = document.getElementById('ul');
  40. var html = '';
  41. // 如果搜索数据存在 把内容添加进去
  42. if (data.s.length) {
  43. // 隐藏掉的ul显示出来
  44. Ul.style.display = 'block';
  45. // 搜索到的数据循环追加到li里
  46. for(var i = 0;i<data.s.length;i++){
  47. html += '<li>'+data.s[i]+'</li>';
  48. }
  49. // 循环的li写入ul
  50. Ul.innerHTML = html;
  51. }
  52. }
  53. // 1.步骤一
  54. window.onload = function(){
  55. // 获取输入框和ul
  56. var Q = document.getElementById('q');
  57. var Ul = document.getElementById('ul');
  58. // 事件鼠标抬起时候
  59. Q.onkeyup = function(){
  60. // 如果输入框不等于空
  61. if (this.value != '') {
  62. // ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆JSONPz重点☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  63. // 创建标签
  64. var script = document.createElement('script');
  65. //给定要跨域的地址 赋值给src
  66. //这里是要请求的跨域的地址 我写的是百度搜索的跨域地址
  67. script.src = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd='+this.value+'&cb=demo';
  68. // 将组合好的带src的script标签追加到body里
  69. document.body.appendChild(script);
  70. }
  71. }
  72. }
  73. </script>
  74. </head>
  75. <body>
  76. <input type="text" id="q" />
  77. <ul id="ul">
  78. </ul>
  79. </body>
  80. </html>

拦截器

概述

SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。

开发者可以自己定义一些拦截器来实现特定的功能。

过滤器与拦截器的区别:拦截器是AOP思想的具体应用。

过滤器

  • servlet规范中的一部分,任何java web工程都可以使用
  • 在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截

    拦截器
  • 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
  • 拦截器只会拦截访问的控制器方法, 如果访问的是jsp/html/css/image/js是不会进行拦截的

自定义拦截器

那如何实现拦截器呢?

想要自定义拦截器,必须实现 HandlerInterceptor 接口。

1、新建一个Moudule , springmvc-07-Interceptor , 添加web支持

2、配置web.xml 和 springmvc-servlet.xml 文件

3、编写一个拦截器

  1. package com.kuang.interceptor;
  2. import org.springframework.web.servlet.HandlerInterceptor;
  3. import org.springframework.web.servlet.ModelAndView;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. public class MyInterceptor implements HandlerInterceptor {
  7. //在请求处理的方法之前执行
  8. //如果返回true执行下一个拦截器
  9. //如果返回false就不执行下一个拦截器
  10. public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
  11. System.out.println("------------处理前------------");
  12. return true;
  13. }
  14. //在请求处理方法执行之后执行
  15. public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
  16. System.out.println("------------处理后------------");
  17. }
  18. //在dispatcherServlet处理后执行,做清理工作.
  19. public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
  20. System.out.println("------------清理------------");
  21. }
  22. }

4、在springmvc的配置文件中配置拦截器

  1. <!--关于拦截器的配置-->
  2. <mvc:interceptors>
  3. <mvc:interceptor>
  4. <!--/** 包括路径及其子路径-->
  5. <!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
  6. <!--/admin/** 拦截的是/admin/下的所有-->
  7. <mvc:mapping path="/**"/>
  8. <!--bean配置的就是拦截器-->
  9. <bean class="com.kuang.interceptor.MyInterceptor"/>
  10. </mvc:interceptor>
  11. </mvc:interceptors>

5、编写一个Controller,接收请求

  1. package com.kuang.controller;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.RequestMapping;
  4. import org.springframework.web.bind.annotation.ResponseBody;
  5. //测试拦截器的控制器
  6. @Controller
  7. public class InterceptorController {
  8. @RequestMapping("/interceptor")
  9. @ResponseBody
  10. public String testFunction() {
  11. System.out.println("控制器中的方法执行了");
  12. return "hello";
  13. }
  14. }

6、前端 index.jsp

  1. <a href="${pageContext.request.contextPath}/interceptor">拦截器测试</a>

7、启动tomcat 测试一下!

验证用户是否登录 (认证用户)

实现思路

1、有一个登陆页面,需要写一个controller访问页面。

2、登陆页面有一提交表单的动作。需要在controller中处理。判断用户名密码是否正确。如果正确,向session中写入用户信息。返回登陆成功。

3、拦截用户请求,判断用户是否登陆。如果用户已经登陆。放行, 如果用户未登陆,跳转到登陆页面

测试:

1、编写一个登陆页面 login.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <h1>登录页面</h1>
  7. <hr>
  8. <body>
  9. <form action="${pageContext.request.contextPath}/user/login">
  10. 用户名:<input type="text" name="username"> <br>
  11. 密码:<input type="password" name="pwd"> <br>
  12. <input type="submit" value="提交">
  13. </form>
  14. </body>
  15. </html>

2、编写一个Controller处理请求

  1. package com.kuang.controller;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.RequestMapping;
  4. import javax.servlet.http.HttpSession;
  5. @Controller
  6. @RequestMapping("/user")
  7. public class UserController {
  8. //跳转到登陆页面
  9. @RequestMapping("/jumplogin")
  10. public String jumpLogin() throws Exception {
  11. return "login";
  12. }
  13. //跳转到成功页面
  14. @RequestMapping("/jumpSuccess")
  15. public String jumpSuccess() throws Exception {
  16. return "success";
  17. }
  18. //登陆提交
  19. @RequestMapping("/login")
  20. public String login(HttpSession session, String username, String pwd) throws Exception {
  21. // 向session记录用户身份信息
  22. System.out.println("接收前端==="+username);
  23. session.setAttribute("user", username);
  24. return "success";
  25. }
  26. //退出登陆
  27. @RequestMapping("logout")
  28. public String logout(HttpSession session) throws Exception {
  29. // session 过期
  30. session.invalidate();
  31. return "login";
  32. }
  33. }

3、编写一个登陆成功的页面 success.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. <h1>登录成功页面</h1>
  8. <hr>
  9. ${user}
  10. <a href="${pageContext.request.contextPath}/user/logout">注销</a>
  11. </body>
  12. </html>

4、在 index 页面上测试跳转!启动Tomcat 测试,未登录也可以进入主页!

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>$Title$</title>
  5. </head>
  6. <body>
  7. <h1>首页</h1>
  8. <hr>
  9. <%--登录--%>
  10. <a href="${pageContext.request.contextPath}/user/jumplogin">登录</a>
  11. <a href="${pageContext.request.contextPath}/user/jumpSuccess">成功页面</a>
  12. </body>
  13. </html>

5、编写用户登录拦截器

  1. package com.kuang.interceptor;
  2. import org.springframework.web.servlet.HandlerInterceptor;
  3. import org.springframework.web.servlet.ModelAndView;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import javax.servlet.http.HttpSession;
  8. import java.io.IOException;
  9. public class LoginInterceptor implements HandlerInterceptor {
  10. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
  11. // 如果是登陆页面则放行
  12. System.out.println("uri: " + request.getRequestURI());
  13. if (request.getRequestURI().contains("login")) {
  14. return true;
  15. }
  16. HttpSession session = request.getSession();
  17. // 如果用户已登陆也放行
  18. if(session.getAttribute("user") != null) {
  19. return true;
  20. }
  21. // 用户没有登陆跳转到登陆页面
  22. request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
  23. return false;
  24. }
  25. public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
  26. }
  27. public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
  28. }
  29. }

6、在Springmvc的配置文件中注册拦截器

  1. <!--关于拦截器的配置-->
  2. <mvc:interceptors>
  3. <mvc:interceptor>
  4. <mvc:mapping path="/**"/>
  5. <bean id="loginInterceptor" class="com.kuang.interceptor.LoginInterceptor"/>
  6. </mvc:interceptor>
  7. </mvc:interceptors>

7、再次重启Tomcat测试!

OK,测试登录拦截功能无误.

文件上传和下载

文件上传是项目开发中最常见的功能之一 ,springMVC 可以很好的支持文件上传,但是

SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。

如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver。

前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。

只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器;

对表单中的 enctype 属性做个详细的说明:

  • application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,

    采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式。
  • multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,

    这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
  • text/plain:除了把空格转换为 "+" 号外,其他字符都不做编码处理,

    这种方式适用直接通过表单发送邮件。
  1. <form action="" enctype="multipart/form-data" method="post">
  2. <input type="file" name="file"/>
  3. <input type="submit">
  4. </form>

一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,

而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应。

在2003年,Apache Software Foundation发布了开源的Commons FileUpload组件,其很快成为Servlet/JSP程序员上传文件的最佳选择。

  • Servlet3.0规范已经提供方法来处理文件上传,但这种上传需要在Servlet中完成。
  • 而Spring MVC则提供了更简单的封装。
  • Spring MVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的。
  • Spring MVC使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类:
  • CommonsMultipartResolver。因此,SpringMVC的文件上传还需要依赖Apache Commons FileUpload的组件

文件上传

1、导入文件上传的jar包,commons-fileupload , Maven会自动帮我们导入他的依赖包 commons-io包;

  1. <!--文件上传-->
  2. <dependency>
  3. <groupId>commons-fileupload</groupId>
  4. <artifactId>commons-fileupload</artifactId>
  5. <version>1.3.3</version>
  6. </dependency>
  7. <!--servlet-api导入高版本的-->
  8. <dependency>
  9. <groupId>javax.servlet</groupId>
  10. <artifactId>javax.servlet-api</artifactId>
  11. <version>4.0.1</version>
  12. </dependency>

2、配置bean:multipartResolver

【注意!!!这个bena的id必须为:multipartResolver , 否则上传文件会报400的错误!在这里栽过坑,教训!】

  1. <!--文件上传配置-->
  2. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  3. <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
  4. <property name="defaultEncoding" value="utf-8"/>
  5. <!-- 上传文件大小上限,单位为字节(10485760=10M) -->
  6. <property name="maxUploadSize" value="10485760"/>
  7. <property name="maxInMemorySize" value="40960"/>
  8. </bean>

CommonsMultipartFile 的 常用方法:

  • String getOriginalFilename():获取上传文件的原名
  • InputStream getInputStream():获取文件流
  • void transferTo(File dest):将上传文件保存到一个目录文件中

测试:

3、编写前端页面

  1. <form action="/upload" enctype="multipart/form-data" method="post">
  2. <input type="file" name="file"/>
  3. <input type="submit" value="upload">
  4. </form>

4、controller

  1. package com.kuang.controller;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.RequestMapping;
  4. import org.springframework.web.bind.annotation.RequestParam;
  5. import org.springframework.web.multipart.commons.CommonsMultipartFile;
  6. import javax.servlet.http.HttpServletRequest;
  7. import java.io.*;
  8. @Controller
  9. public class FileController {
  10. //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
  11. //批量上传CommonsMultipartFile则为数组即可
  12. @RequestMapping("/upload")
  13. public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {
  14. //获取文件名 : file.getOriginalFilename();
  15. String uploadFileName = file.getOriginalFilename();
  16. //如果文件名为空,直接回到首页!
  17. if ("".equals(uploadFileName)){
  18. return "redirect:/index.jsp";
  19. }
  20. System.out.println("上传文件名 : "+uploadFileName);
  21. //上传路径保存设置
  22. String path = request.getServletContext().getRealPath("/upload");
  23. //如果路径不存在,创建一个
  24. File realPath = new File(path);
  25. if (!realPath.exists()){
  26. realPath.mkdir();
  27. }
  28. System.out.println("上传文件保存地址:"+realPath);
  29. InputStream is = file.getInputStream(); //文件输入流
  30. OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流
  31. //读取写出
  32. int len=0;
  33. byte[] buffer = new byte[1024];
  34. while ((len=is.read(buffer))!=-1){
  35. os.write(buffer,0,len);
  36. os.flush();
  37. }
  38. os.close();
  39. is.close();
  40. return "redirect:/index.jsp";
  41. }
  42. }

5、测试上传文件

采用file.Transto 来保存上传的文件

1、编写Controller

  1. /*
  2. * 采用file.Transto 来保存上传的文件
  3. */
  4. @RequestMapping("/upload2")
  5. public String fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
  6. //上传路径保存设置
  7. String path = request.getServletContext().getRealPath("/upload");
  8. File realPath = new File(path);
  9. if (!realPath.exists()){
  10. realPath.mkdir();
  11. }
  12. //上传文件地址
  13. System.out.println("上传文件保存地址:"+realPath);
  14. //通过CommonsMultipartFile的方法直接写文件(注意这个时候)
  15. file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));
  16. return "redirect:/index.jsp";
  17. }

2、前端表单提交地址修改

3、访问提交测试

文件下载

文件下载步骤:

1、设置 response 响应头

2、读取文件 -- InputStream

3、写出文件 -- OutputStream

4、执行操作

5、关闭流 (先开后关)

代码实现:

  1. @RequestMapping(value="/download")
  2. public String downloads(HttpServletResponse response ,HttpServletRequest request) throws Exception{
  3. //要下载的图片地址
  4. String path = request.getServletContext().getRealPath("/upload");
  5. String fileName = "基础语法.jpg";
  6. //1、设置response 响应头
  7. response.reset(); //设置页面不缓存,清空buffer
  8. response.setCharacterEncoding("UTF-8"); //字符编码
  9. response.setContentType("multipart/form-data"); //二进制传输数据
  10. //设置响应头
  11. response.setHeader("Content-Disposition",
  12. "attachment;fileName="+URLEncoder.encode(fileName, "UTF-8"));
  13. File file = new File(path,fileName);
  14. //2、 读取文件--输入流
  15. InputStream input=new FileInputStream(file);
  16. //3、 写出文件--输出流
  17. OutputStream out = response.getOutputStream();
  18. byte[] buff =new byte[1024];
  19. int index=0;
  20. //4、执行 写出操作
  21. while((index= input.read(buff))!= -1){
  22. out.write(buff, 0, index);
  23. out.flush();
  24. }
  25. out.close();
  26. input.close();
  27. return null;
  28. }

前端的话

  1. <a href="/download">点我下载</a>

测试,文件下载OK。

SpringMVC学习(二)的更多相关文章

  1. (转)SpringMVC学习(二)——SpringMVC架构及组件

    http://blog.csdn.net/yerenyuan_pku/article/details/72231385 相信大家通过前文的学习,已经对SpringMVC这个框架多少有些理解了.还记得上 ...

  2. SpringMVC学习(二)——SpringMVC架构及组件(及其运行原理)-转载

    相信大家通过前文的学习,已经对SpringMVC这个框架多少有些理解了.还记得上一篇文章中SpringMVC的处理流程吗?  这个图大致描述了SpringMVC的整个处理流程,这个流程图还是相对来说比 ...

  3. SpringMVC学习二

    处理请求 今天学了三种请求,一种是 PathVariable ,一种是 RequestParam ,还有一种是CookieValue,并实现简单rest增删改查 上代码 package com.spr ...

  4. springMVC学习二 原始springMVC环境搭建

    第一步:导入jar包 第二步:配置DispatcherServlet DispatcherServlet本质是一个Servlet,在spring-webmvc包中,在servlet2.5之前  spr ...

  5. springMVC学习总结(二)路径映射和请求方法限定

    springMVC学习总结(二)路径映射和请求方法限定 一.路径映射 无参数的访问路径 对springmvc项目的访问路径,是由根路径和子路径组成:在注解式开发中,根路径标注在类名之上,子路径标注在方 ...

  6. SpringMVC学习笔记之二(SpringMVC高级参数绑定)

    一.高级参数绑定 1.1 绑定数组 需求:在商品列表页面选中多个商品,然后删除. 需求分析:功能要求商品列表页面中的每个商品前有一个checkbok,选中多个商品后点击删除按钮把商品id传递给Cont ...

  7. SpringMVC入门学习(二)

    SpringMVC入门学习(二) ssm框架 springMVC  在上一篇博客中,我简单介绍了一下SpringMVC的环境配置,和简单的使用,今天我们将进一步的学习下Springmvc的操作. mo ...

  8. springmvc学习总结(二) -- maven+springmvc+spring+mybatis+mysql详细搭建整合过程讲解

    @_@ 写在最前 之前分享过下面这几篇: mybatis学习笔记(五) -- maven+spring+mybatis从零开始搭建整合详细过程(上)(附demo和搭建过程遇到的问题解决方法) myba ...

  9. (转)SpringMVC学习(十二)——SpringMVC中的拦截器

    http://blog.csdn.net/yerenyuan_pku/article/details/72567761 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter, ...

随机推荐

  1. python open函数初习

    open("路径","打开方式")  打开方式:'r'只读模式,‘w’写模式,‘a’追加模式 ‘b’二进制模式,‘+’读/写模式.例: fh=open(&quo ...

  2. Ubuntu 磁盘满了处理方法。

    Ubuntu 磁盘满了处理方法: 1. 如果是虚拟机安装ubuntu,直接给虚拟机安装ubuntu 系统所在的盘符动态分配一点磁盘容量,就可以了. 2. 如果不是虚拟机安装ubuntu,那么有两个办法 ...

  3. 1、Entity Framework Core 3.1入门教程-概述和准备工作

    本文章是根据 微软MVP solenovex(杨旭)老师的视频教程编写而来,再加上自己的一些理解. 视频教程地址:https://www.bilibili.com/video/BV1xa4y1v7rR ...

  4. 安装openssl后yum不能使用的解决办法

    重新编译安装ioenssl后,发现yum命令不能使用,找到如下解决办法 提示错误是 openssl: /usr/lib/x86_64-linux-gnu/libssl.so.1.1: version ...

  5. 全局api 2020/8/14

    // 注意:每次调用 $.get() 或 $.post() 或 $.ajax() 的时候, // 会先调用 ajaxPrefilter 这个函数 // 在这个函数中,可以拿到我们给Ajax提供的配置对 ...

  6. e3mall商城的归纳总结1之项目的架构

    首先来谈谈e3mall商城,e3mall商城是黑马推出一个学习的项目,前身是淘淘商城.两个用的技术差不多.,但由于后期加了一些新技术,更名为e3mall商城.本商城为分布式商城,主要用到的技术使mav ...

  7. EventDispatcher

    事件分发类,提供事件注册.移除.触发功能 采用delegate.dictionary实现 支持自定义事件.事件采用字符串方式标识 支持 0,1,2,3,4 等5种不同参数个数的回调函数   // 路由 ...

  8. 用于测试SqlAnalyzer1.00的十七个测试用例

    SqlAnalyzer功能:解析SQL语句,具体到字段,表和条件,并将其整理后输出格式化文本. 1. 原文=select a from b 整理后文本= select a from b 2. 原文=s ...

  9. agumaster 出现实际股票数据

    工程下载:https://files.cnblogs.com/files/xiandedanteng/agumaster20200430-3.zip --2020-04-30--

  10. ssh工具 (Java)

    执行shell命令.下载文件... package com.sunsheen.blockchain.admin.utils; import java.io.BufferedReader; import ...