赞
踩
Java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取Action中可重用部分代码的方式,动态拦截Action调用的对象(也就是controller层)。
Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。
自定义一个拦截器,只需要实现HandlerInterceptor接口即可,该接口包含三个方法:
@Component public class SessionIntercepter implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("拦截器 preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 设置字符编码 response.setCharacterEncoding("UTF-8"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println(response.getCharacterEncoding()); } }
想要Spring Boot 拦截器生效很简单,只需要定义一个配置类,实现 WebMvcConfigurer 接口,实现其中的 addInterceptors() 方法即可。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private SessionIntercepter sessionIntercepter;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 拦截器拦截路径
registry.addInterceptor(sessionIntercepter).addPathPatterns("/**");
}
}
运用例子:
Filter 也称为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如JSP,servlet,静态图片文件或静态HTML文件进行拦截,从而实现一些特殊功能。例如实现URL级别的权限控制、过滤敏感词汇、压缩响应信息等一些高级功能。
当客户端发出Web资源的请求时,Web服务器根据应用程序配置文件设置的过滤规则进行检查,若客户请求满足过滤规则,则对请求/响应进行拦截,对请求头和请求数据进行检查或改动,并依次通过过滤器链,最后把请求/响应交给请求的Web资源处理。请求信息在过滤器链中可以被修改,也可以根据条件让请求不发往资源处理器,并直接向客户端返回一个响应。当资源处理器完成了对资源的处理后,响应信息将逐级逆向返回。同样在这个过程中,用户可以修改响应信息,从而完成一定的任务,如图:
服务器会按照过滤器定义的先后顺序组成一条链,然后一次执行其中的doFilter()方法。执行的顺序如图所示,执行第一个过滤器的chain.doFilter()之前的代码,第二个过滤器的chain.doFilter()之前的代码,请求的资源,第二个过滤器的chain.doFilter()之后的代码,第一个过滤器chain.doFilter()之后的代码,最后返回响应。
自定义 Filter,只需要实现 javax.servlet.Filter 接口,重写其中的方法即可。
@Component
public class WeFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 继续执行下一个 filter
filterChain.doFilter(servletRequest, servletResponse);
}
}
方法一:
配置类中使用@Bean注入(推荐使用)
@Configuration public class FilterConfig { @Autowired private WeFilter weFilter1; @Autowired private WeFilter weFilter2; @Bean public FilterRegistrationBean injectFilterOne() { FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(weFilter1); registrationBean.addUrlPatterns("/*"); registrationBean.setName("filter_one"); // 优先级 registrationBean.setOrder(1); return registrationBean; } @Bean public FilterRegistrationBean injectFilterTwo() { FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(weFilter2); registrationBean.addUrlPatterns("/*"); registrationBean.setName("filter_one"); // 优先级 registrationBean.setOrder(2); return registrationBean; } }
注意:设置的优先级别决定了过滤器的执行顺序
方法二:
使用@WebFilter,@WebFilter时Servlet3.0的一个注解,用于标注一个Filter,Spring Boot也是支持这种方式的,只需要在自定义的Filter上标注该注解即可。
@WebFilter(filterName = "filter_one", urlPatterns = {"/*"})
public class WeFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 继续执行下一个 filter
filterChain.doFilter(servletRequest, servletResponse);
}
}
要想@WebFilter注解生效,需要在配置类上标注另外一个注解@ServletComponentScan用于扫描使其生效。
@SpringBootApplication
@ServletComponentScan(value = {"com.example.demo.filter"})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
运用例子:
对于前后端分离的项目来说跨越是一个难题,对于跨越问题有很多解决方案,比如JSONP,网关支持等。用过滤器也可以解决跨越问题,原理很简单,只需要在请求头中添加相应支持跨越的内容即可。
@Component
public class WeFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
// 继续执行下一个 filter
filterChain.doFilter(servletRequest, servletResponse);
}
}
配置类中注入
@Configuration public class FilterConfig { @Autowired private WeFilter weFilter; @Bean public FilterRegistrationBean injectFilterOne() { FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(weFilter); registrationBean.addUrlPatterns("/*"); registrationBean.setName("filter_one"); // 优先级 registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); return registrationBean; } }
过滤器的内容虽然简单,但是在实际开发中不可或缺,比如常用的权限控制框架Shiro,Spring Security,内部都是使用过滤器,了解一下对以后的深入学习有着固本的作用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。