SpringMVC学习笔记:springmvc-05

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标签

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

  2. 完善基础架构

    配置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,测试

在这里插入图片描述

  1. 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>
    
  2. 使用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处理,最简单,最通用

  1. springmvc配置文件中需要导入静态资源过滤,后面会手动导入jQuery

    <!--使用jQuery需要配置,静态资源过滤-->
    <mvc:default-servlet-handler />
    
  2. 下载jQuery资源,创建/web/static/js目录,手动导入项目中

在这里插入图片描述

下载资源方法:直接搜索jQuery,进入官网,点击下载,右键另存为。

  1. 编写一个 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***");
        }
    }
    
  2. 编写 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>
    
  3. 启动Tomcat测试!打开浏览器的控制台,当鼠标离开输入框的时候,可以看到发出了一个ajax的请求!是后台返回给我们的结果!测试成功

SpringMVC实现

  1. 实体类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;
}
  1. 请求获取一个集合对象,展示到前端页面
 @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格式返回
    }
  1. 前端页面 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>

  1. 测试数据成功回显

在这里插入图片描述

9.4 注册效果提示

在测试一个Demo,思考下平时注册的时候,输入框后面的实时提示是怎么做到的,如何优化。

  1. 写一个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;
    }
    
  2. 前端页面 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>
    
  3. 测试效果:鼠标离开文本输入框焦点时,动态相应请求,会完成一次局部刷新!【这里信息带中文,记得处理 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 接口。

  1. 新建一个Module,springmvc-07-Interceptor,添加web支持

  2. 配置web.xml 和 applicationContext.xml。确定lib库导入

  3. 编写一个拦截器

    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("***********清理!************");
        }
    }
    
  4. 在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>
    
  5. 编写一个Controller,接收请求

    @Controller
    public class InterceptorController {
        @RequestMapping("/inct")
        @ResponseBody
        public String testFunction() {
            System.out.println("控制器中的方法执行了");
            return "hello";
        }
    }
    
  6. 前端测试请求 index.jsp

    <a href="${pageContext.request.contextPath}/inct">拦截器测试</a>
    
  7. 启动Tomcat,测试!

在这里插入图片描述

可以看到,在发生请求的时候,控制器处理请求前会先经过拦截器,然后再处理请求。

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

实现思路

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

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

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

测试:

  1. 编写一个登录页面 /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>
    
  2. 编写一个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";
        }
    }
    
  3. 编写一个登录成功的页面 /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>
    
  4. 在 index.jsp 页面测试跳转!启动Tomcat测试,未登录也可以进入主页!

    <%--登录--%>
    <a href="${pageContext.request.contextPath}/user/jumplogin">登录</a>
    <a href="${pageContext.request.contextPath}/user/jumpSuccess">成功页面</a>
    
  5. 编写用户登录拦截器

    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("***********清理!************");
        }
    }
    
  6. 在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>
    
  7. 再次启动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 文件上传

  1. 导入文件上传的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>
    
  2. 配置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):将上传文件保存到一个目录中
  3. 编写前端页面

    <form action="/upload" enctype="multipart/form-data" method="post">
        <input type="file" name="file"/>
        <input type="submit" value="upload">
    </form>
    
  4. 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";
        }
    }
    
  5. 测试上传文件,OK!

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

  1. 编写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";
    }
    
  2. 前端提交表单修改

    <form action="${pageContext.request.contextPath}/upload2" enctype="multipart/form-data" method="post">
        <input type="file" name="file"/>
        <input type="submit" value="upload2">
    </form>
    
  3. 访问提交测试,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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值