SpringMVC拦截器 和servlet过滤器 的使用

servlet过滤器

1.什么是过滤器

过滤器实际上就是对web资源进⾏拦截,做⼀些处理后再交给下⼀个过滤器或servlet处理,通常都 是⽤来拦截request进⾏处理的,也可以对返回的response进⾏拦截处理,可以同时设置多个过滤器。过滤器依赖于servlet,一个过滤器可以加在多个servlet上,(多个过滤器也可以加在一个servlet上)

SpringMVC拦截器 和servlet过滤器 的使用_第1张图片

2.过滤器的语法格式

实现Javax.serlvet.Filter接口,重写里面的方法(对应servlet-api.jar)

package util;


import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class FirstFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化filter");//当服务器启动时执行init
    }

    @Override   //请求和响应时都会执行这个方法
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器开始");

        //调取下一个过滤器,或者调取servlet
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("过滤器结束");

    }

    @Override
    public void destroy() {
        System.out.println("销毁filter");
    }
}

3.在web.xml⽂件中配置


 过滤器名称
 过滤器所在的路径
 
 
 过滤器名称
 需要过滤的资源
 

示例:

  
        f1
        
            util.FirstFilter
        
    
    
        f1
        /*
    

4.使⽤场景

1.如何防⽌⽤户未登录就执⾏后续操作

String name=(String)session.getAttribute("key");

if(name==null){ //跳转到登录⻚⾯ }

.2.设置编码⽅式--统⼀设置编码

3.加密解密(密码的加密和解密)

4.⾮法⽂字筛选

5.下载资源的限制 过滤器的特点:在servlet之前和之后都会被执⾏

5.过滤器中的url-pattern中的 / 和 /*  和/login

 
        testFilter1
        /*
    

会过滤所有请求,包括对静态资源的访问,都会进入过滤器。

会匹配所有的url:路径型的和后缀型的url(包括/springmvc,.jsp,.js和*.html等)。 这种形式将会覆盖所有其它的servlet。不管你发出了什么样的请求,最终都会在这个servlet中结束。因此,对于servlet来说,这是一个很糟糕的URL模式。通常来讲,你只会想要在一个Filter中使用这种模式。


        testFilter1
        /
    

会匹配到/springmvc这样的路径型url,不会匹配到模式为*.jsp这样的后缀型url。

这时如果有静态资源的访问,要再处理对静态资源的访问不到的问题。 


        testFilter2
        /login
    

只会过滤/login访问路径

例子:验证用户登录

过滤器

package util;


import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class FirstFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化filter");//当服务器启动时执行init
    }

    @Override   //请求和响应时都会执行这个方法
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器开始");
        //处理乱码
        HttpServletRequest request=(HttpServletRequest)servletRequest;
        HttpServletResponse response=(HttpServletResponse)servletResponse;
        request.setCharacterEncoding("utf-8");

        //防止用户在未登录的情况下访问资源
        String requestURI = request.getRequestURI();//获得请求地址
        System.out.println("requestURI="+requestURI);
        Object username = request.getSession().getAttribute("username");

        if(requestURI.endsWith("testsession.jsp")&&username==null){
            response.sendRedirect("index.jsp");
        }

        //调取下一个过滤器,或者调取servlet
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("过滤器结束");

    }

    @Override
    public void destroy() {
        System.out.println("销毁filter");
    }
}

后端

package servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet(urlPatterns = "/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       resp.sendRedirect("error.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("login-servlet被执行");
        //1.接收参数
        String username = req.getParameter("username");
        String pass = req.getParameter("pass");
        //2.判断正误
        if("admin".equals(username)&&"123456".equals(pass)){
            //登录成功
            //session存值
            HttpSession session = req.getSession();
            session.setAttribute("username",username);
            session.setAttribute("password",pass);
            session.setMaxInactiveInterval(60*30);//单位是秒
            //重定向或者转发时,session数据是不会丢失的,重定向时,request中的数据会丢失
            resp.sendRedirect("success.jsp");
        }else{
            //登录失败
            //1.后台创建cookie
            Cookie cookie = new Cookie("uname",username);
            //2.返回给前端
            resp.addCookie(cookie);
            resp.sendRedirect("index.jsp");
        }
    }
}

前端


<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    $Title$
  
  

  <%
    Cookie[] cookies = request.getCookies();
    String value ="";
    if(cookies!=null&&cookies.length>0){
      for (Cookie cookie : cookies) {
        if(cookie.getName().equals("uname")){
          value = cookie.getValue();
          break;
        }
      }
    }
    pageContext.setAttribute("unamecookie",value);

  %>

  

登录

用户名:
密码:

SpringMVC 中的 拦截器

1.概念


java中的拦截器是动态拦截action调用的对象。依赖于web框架,在springmvc中依赖于SpringMVC框架,在实现上基于Java的反射机制,属于AOP的一种应用,作用类似于过滤器,但是拦截器只能对Controller请求进行拦截,对其他的直接访问静态资源的请求无法拦截处理。
 

拦截器( Interceptor)是非常重要的,它的主要作用是拦截指定的用户请求,并进行 相应的预处理与后处理。

2.拦截时间

拦截的时间点在“处理器映射器HandlerMapping根据用户提交的请求映射出了所要执行的处理器类,并 且也找到了要执行该处理器类的处理器适配器,在处理器适配器HandlerAdaptor执行处理器之前”。

在处理器映射器映射出所要执行的处理器类时,已经将拦截器与处理器组合为了一个处理器执行链 HandlerExecutionChain,并返回给了前端控制器。

3.实现拦截器

自定义拦截器,需要实现 HandlerInterceptor 接口。而该接口中含有三个方法:

public interface HandlerInterceptor {


default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return true;
	}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable ModelAndView modelAndView) throws Exception {
	}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable Exception ex) throws Exception {
	}

}

4.拦截器方法说明

preHandle(request,response, Object handler):

该方法在处理器方法执行之前执行。其返回值为boolean,若为true,则紧接着会执行处理器方法,且 会将afterCompletion()方法放入到一个专门的方法栈中等待执行。 postHandle(request,response, Object handler,modelAndView):

该方法在处理器方法执行之后执行。处理器方法若最终未被执行,则该方法不会执行。由于该方法是在处 理器方法执行完后执行,且该方法参数中包含 ModelAndView,所以该方法可以修改处理器方法的处理结果 数据,且可以修改跳转方向。

afterCompletion(request,response, Object handler, Exception ex): 当 preHandle()方法返回true时,会将该方法放到专门的方法栈中,等到对请求进行响应的所工作完 成之后才执行该方法。即该方法是在前端控制器渲染(数据填充)了响应页面之后执行的,此时对 ModelAndView再操作也对响应无济于事。

afterCompletion最后执行的方法,清除资源,例如在Controller方法中加入数据

5.方法使用场景

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 {

    //执行时间: 控制器方法执行之前,在ModelAndView返回之前
    //使用场景: 登录验证
    // 返回值 true : 继续执行控制器方法 表示放行    false: 不会继续执行控制器方法,表示拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle-------------------");
        return true;
    }

    //执行时间: 控制器方法执行之hou后,在ModelAndView返回之前,有机会修改返回值
    //使用场景: 日记记录,记录登录的ip,时间
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle-------------------");
    }

    //执行时间: 控制器方法执行之后,在ModelAndView返回之后,没有机会修改返回值
    //使用场景: 全局资源的一些操作
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion-------------------");
    }

6.设置多个拦截器所执行的顺序

(默认对三种方法都实现 )

preHandle1->  preHandle2  ->postHande2  ->perHande2 ->afterCompletion2 ->afterCompletion1

测试

上传的文件是否符合定义的格式,不符合的进行拦截

环境搭建      

1.需要在maven 的pom.xml中引入 的依赖和 插件  


        
            org.springframework
            spring-webmvc
            5.2.13.RELEASE
        
        
        
            javax.servlet
            javax.servlet-api
            4.0.1
            provided
        


        
            
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.0
                
                    1.8
                    1.8
                
            
            
            
                org.apache.tomcat.maven
                tomcat7-maven-plugin
                2.2
                
                    /
                    8080
                
            
        
    

2.springMVC 的xml文件中拦截路径的配置  

拦截关键字路径

当使用/user/xxx拦截时候

这时又多了一个需求就是拦截   /user/manager/xxxx

如何对含有关键字manger路径进行拦截

manger前面如果只有一层路径  使用/*/manger/**    例如  user/manger/xxxx

manger前面含义多层路径  使用    /**/manger/**      此时前面如果没有  路径 由于/**资源通配符的作用,过滤也起作用

  
    


 
    
        
        
            
            
        

        
            
            
        
    

如何放行特定的请求路径 

使用

 
        
        
            
            
            
            
            
           
            
          
            
            
            
            
        
    

3.实现类

package com.kkb.interceptor;

import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;
import java.util.Map
public class FileInterceptor implements HandlerInterceptor {
    /**
     * 在文件上传之前判断文件后缀是否合法
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断是否是文件上传的请求
        boolean flag=true;
        if(request instanceof MultipartHttpServletRequest){
            //单一上传文件  method="post" enctype="multipart/form-data"
            MultipartHttpServletRequest multipartRequest= (MultipartHttpServletRequest) request;
            Map fileMap = multipartRequest.getFileMap();
            //遍历文件
               //通过entrySet
//            Set> entries = fileMap.entrySet();
//            for (Map.Entry entry : entries) {
//                System.out.println("key:"+entry.getKey()+" "
//                        +"value:"+entry.getValue());
//            }
            Iterator iterator = fileMap.keySet().iterator();
            while(iterator.hasNext()){
                String key = iterator.next();
                MultipartFile file = multipartRequest.getFile(key);
                String originalFilename = file.getOriginalFilename();
                String hz = originalFilename.substring(originalFilename.lastIndexOf("."));
                //判断后缀是否合法
                if(!hz.toLowerCase().equals(".png") && !hz.toLowerCase().equals(".jpg")){
                    request.getRequestDispatcher("/jsp/fileTypError.jsp").forward(request,response);
                    flag=false;
                }
            }
        }
        return flag;
    }

拦截器实现验证登录

1.aa 

2.bb

过滤器和拦截器的区别:

1 、拦截器是基于java的反射机制的,而过滤器是基于函数回调。

2 、拦截器不依赖与servlet容器,过滤器依赖与servlet容器。

3 、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。

4 、拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。

5 、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

参考:java中过滤器和拦截器的区别

你可能感兴趣的:(springMVC,spring,java,后端)