NoteDeep

拦截器

概述
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、编写一个拦截器
package com.kuang.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 httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {        System.out.println("------------处理前------------");        return true;   }
   //在请求处理方法执行之后执行    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {        System.out.println("------------处理后------------");   }
   //在dispatcherServlet处理后执行,做清理工作.    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) 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.kuang.interceptor.MyInterceptor"/>    </mvc:interceptor> </mvc:interceptors>
5、编写一个Controller,接收请求
package com.kuang.controller;
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;
//测试拦截器的控制器 @Controller public class InterceptorController {
   @RequestMapping("/interceptor")    @ResponseBody    public String testFunction() {        System.out.println("控制器中的方法执行了");        return "hello";   } }
6、前端 index.jsp
<a href="${pageContext.request.contextPath}/interceptor">拦截器测试</a>
7、启动tomcat 测试一下!
验证用户是否登录 (认证用户)
实现思路
1、有一个登陆页面,需要写一个controller访问页面。
2、登陆页面有一提交表单的动作。需要在controller中处理。判断用户名密码是否正确。如果正确,向session中写入用户信息。返回登陆成功。
3、拦截用户请求,判断用户是否登陆。如果用户已经登陆。放行, 如果用户未登陆,跳转到登陆页面
测试:
1、编写一个登陆页面  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处理请求
package com.kuang.controller;
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpSession;
@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、编写一个登陆成功的页面 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 页面上测试跳转!启动Tomcat 测试,未登录也可以进入主页!
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html>  <head>    <title>$Title$</title>  </head>  <body>  <h1>首页</h1>  <hr> <%--登录--%>  <a href="${pageContext.request.contextPath}/user/jumplogin">登录</a>  <a href="${pageContext.request.contextPath}/user/jumpSuccess">成功页面</a>  </body> </html>
5、编写用户登录拦截器
package com.kuang.interceptor;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException;
public class LoginInterceptor implements HandlerInterceptor {
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws 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);        return false;   }
   public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
  }        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
  } }
6、在Springmvc的配置文件中注册拦截器
<!--关于拦截器的配置--> <mvc:interceptors>    <mvc:interceptor>        <mvc:mapping path="/**"/>        <bean id="loginInterceptor" class="com.kuang.interceptor.LoginInterceptor"/>    </mvc:interceptor> </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:除了把空格转换为 "+" 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。
<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中完成。
  • 而Spring MVC则提供了更简单的封装。
  • Spring MVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的。
  • Spring MVC使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类:
  • CommonsMultipartResolver。因此,SpringMVC的文件上传还需要依赖Apache Commons FileUpload的组件。
文件上传
1、导入文件上传的jar包,commons-fileupload , Maven会自动帮我们导入他的依赖包 commons-io包;
<!--文件上传--> <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>
2、配置bean:multipartResolver
注意!!!这个bena的id必须为:multipartResolver , 否则上传文件会报400的错误!在这里栽过坑,教训!
<!--文件上传配置--> <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
package com.kuang.controller;
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.servlet.http.HttpServletRequest; import java.io.*;
@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)){            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、前端表单提交地址修改
3、访问提交测试,OK!
文件下载
文件下载步骤:
1、设置 response 响应头
2、读取文件 -- InputStream
3、写出文件 -- OutputStream
4、执行操作
5、关闭流 (先开后关)
代码实现:
@RequestMapping(value="/download") public String downloads(HttpServletResponse response ,HttpServletRequest request) throws Exception{    //要下载的图片地址    String  path = request.getServletContext().getRealPath("/upload");    String  fileName = "基础语法.jpg";
   //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原生的方式对比一下,就可以知道这个便捷多了!
拦截器及文件操作在我们开发中十分重要,一定要学会使用!

评论列表

    拦截器