企业网站优化的方式,萍乡市建设局网站王丽,包包网站建设,网站建设验收程序来源 | blog.csdn.net/qq_38020915/article/details/116431612作者 | dingwen_blog一、关系图理解二、区别1.过滤器过滤器是在web应用启动的时候初始化一次, 在web应用停止的时候销毁可以对请求的URL进行过滤, 对敏感词过滤挡在拦截器的外层实现的是 javax.servlet.Filter 接口… 来源 | blog.csdn.net/qq_38020915/article/details/116431612作者 | dingwen_blog一、关系图理解二、区别1.过滤器过滤器是在web应用启动的时候初始化一次, 在web应用停止的时候销毁可以对请求的URL进行过滤, 对敏感词过滤挡在拦截器的外层实现的是 javax.servlet.Filter 接口 是 Servlet 规范的一部分在请求进入容器后但在进入servlet之前进行预处理请求结束是在servlet处理完以后依赖Web容器会多次执行1.1HttpServletRequestWrapper“在请求到达之前对 request 进行修改package com.dingwen.lir.filter;import lombok.extern.slf4j.Slf4j;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.Arrays;/*** 在请求到达之前对 request 进行修改*/
Slf4j
public class RequestWrapper extends HttpServletRequestWrapper {public RequestWrapper(HttpServletRequest request) {super(request);log.info(RequestWrapper);}Overridepublic String getParameter(String name) {// 可以对请求参数进行过滤return super.getParameter(name);}Overridepublic String[] getParameterValues(String name) {// 对请求参数值进行过滤
// String[] values super.getRequest().getParameterValues(name);
// return super.getParameterValues(name);return t e s t.split( );}}
1.2 OncePerRequestFilter“OncePerRequestFilter顾名思义它能够确保在一次请求中只通过一次filterpackage com.dingwen.lir.filter;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;/*** 请求过滤器* OncePerRequestFilter:* OncePerRequestFilter顾名思义它能够确保在一次请求中只通过一次filter.* 大家常识上都认为一次请求本来就只filter一次为什么还要由此特别限定呢往往我们的常识和实际的实现并不真的一样经过一番资料的查阅此方法是为了兼容不同的web container* 也就是说并不是所有的container都入我们期望的只过滤一次servlet版本不同执行过程也不同* 因此为了兼容各种不同运行环境和版本默认filter继承OncePerRequestFilter是一个比较稳妥的选择。**/
Slf4j
public class RequestFilter extends OncePerRequestFilter {Overridepublic void destroy() {super.destroy();log.info(RequestFilter destroy);}/*OncePerRequestFilter.doFilter方法中通过request.getAttribute判断当前过滤器是否已执行若未执行过则调用doFilterInternal方法交由其子类实现*/Overrideprotected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {try {RequestWrapper requestWrapper new RequestWrapper(httpServletRequest);filterChain.doFilter(requestWrapper, httpServletResponse);log.info(RequestFilter);log.info(Arrays.toString(requestWrapper.getParameterValues(name)));} catch (Exception exception) {httpServletResponse.setCharacterEncoding(utf-8);httpServletResponse.setContentType(application/json; charsetutf-8);PrintWriter writer httpServletResponse.getWriter();writer.write(exception.toString());}}
}
1.3 配置package com.dingwen.lir.configuration;import com.dingwen.lir.filter.RequestFilter;
import com.dingwen.lir.filter.RequestWrapper;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.servlet.Filter;/*** 过滤器配置类**/
Configuration
public class FilterConfig {Beanpublic RequestFilter requestFilter(){return new RequestFilter();}Beanpublic FilterRegistrationBeanRequestFilter registrationBean() {FilterRegistrationBeanRequestFilter registrationBean new FilterRegistrationBean();registrationBean.setFilter(requestFilter());registrationBean.addUrlPatterns(/filter/*);registrationBean.setName(RequestFilter);//过滤器的级别值越小级别越高越先执行registrationBean.setOrder(1);return registrationBean;}
}
2.拦截器实现 org.springframework.web.servlet.HandlerInterceptor 接口动态代理拦截器应用场景, 性能分析, 权限检查, 日志记录是一个Spring组件并由Spring容器管理并不依赖Tomcat等容器是可以单独使用的。不仅能应用在web程序中也可以用于Application、Swing等程序中是在请求进入servlet后在进入Controller之前进行预处理的Controller 中渲染了对应的视图之后请求结束2.1登录拦截package com.dingwen.lir.interceptor;import com.dingwen.lir.entity.User;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** 登录拦截**/
Component
public class PageInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {User user (User)request.getSession().getAttribute(user);if (!ObjectUtils.isEmpty(user)) {return true;} else {// 不管是转发还是重定向必须返回false。否则出现多次提交响应的错误redirect(request, response);return false;}}/** 对于请求是ajax请求重定向问题的处理方法* param request* param response**/public void redirect(HttpServletRequest request, HttpServletResponse response) throws IOException {if(XMLHttpRequest.equals(request.getHeader(X-Requested-With))){// ajax//获取当前请求的路径response.setHeader(Access-Control-Expose-Headers, REDIRECT,CONTENT_PATH);//告诉ajax我是重定向response.setHeader(REDIRECT, REDIRECT);//告诉ajax我重定向的路径StringBuffer url request.getRequestURL();String contextPath request.getContextPath();response.setHeader(CONTENT_PATH, url.replace(url.indexOf(contextPath) contextPath.length(), url.length(), /).toString());}else{// httpresponse.sendRedirect( /page/login);}response.getWriter().write(403);response.setStatus(HttpServletResponse.SC_FORBIDDEN);}}2.2配置package com.dingwen.lir.configuration;import com.dingwen.lir.interceptor.PageInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** mvc 控制器配置* MyWebMvcConfigurer: Springboot2.x以后版本使用**/
Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {/** 拦截器依赖于Spring容器此处拦截了所有需要对静态资源进行放行*/Overridepublic void addInterceptors(InterceptorRegistry registry) {// 拦截器默认的执行顺序就是它的注册顺序也可以通过Order手动设置控制值越小越先执行。
// registry.addInterceptor(new PageInterceptor()).addPathPatterns(/**).order()registry.addInterceptor(new PageInterceptor()).addPathPatterns(/**).excludePathPatterns(/page/login, /user/login,/page/ajax,/static/**);}/** 不要要写控制器即可完成页面跳转访问* param registry*/Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController(/page/ajax).setViewName(ajax);}/** 自定义静态资源映射Spring Boot 默认为我们提供了静态资源映射classpath:/META-INF/resourcesclasspath:/resourcesclasspath:/staticclasspath:/public优先级META-INF/resources resources static public* param registry**/
// Override
// public void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler(/static/**).addResourceLocations(classpath:/static/);registry.addResourceHandler(/static/**).addResourceLocations(file:E:/static/);
// }
}3.监听器实现 javax.servlet.ServletRequestListener, javax.servlet.http.HttpSessionListener, javax.servlet.ServletContextListener 等等接口主要用来监听对象的创建与销毁的发生, 比如 session 的创建销毁, request 的创建销毁, ServletContext 创建销毁三、注意1.静态资源问题“SpringBoot2.x以后版本拦截器也会拦截静态资源在配置拦截器是需要将姿态资源放行。 /** 拦截器依赖于Spring容器此处拦截了所有需要对静态资源进行放行*/Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new PageInterceptor()).addPathPatterns(/**).excludePathPatterns(/page/login, /user/login,/page/ajax,/static/**);}“SpringBoot2.x 自定义静态资源映射spring:mvc:static-path-pattern: /static/**“默认目录 classpath:/META-INF/resources classpath:/resources classpath:/static classpath:/public 优先级META-INF/resources resources static public2.登录拦截ajax重定向“由于ajax是异步的还在当前页面进行的局部请求。当拦截到登录请求时即使重定向也无法生效。需采用服务端给地址由前端进行跳转。详细见登录拦截器代码。// 前端处理
!DOCTYPE html
html langen
headmeta charsetUTF-8titleAJAX/titlescript srchttps://code.jquery.com/jquery-3.0.0.min.js/script
/head
bodybuttonUSER/button
/body
/htmlscript$.ajaxSetup({complete:function(xhr,status){//拦截器实现超时跳转到登录页面let win window;// 通过xhr取得响应头let REDIRECT xhr.getResponseHeader(REDIRECT);//如果响应头中包含 REDIRECT 则说明是拦截器返回的需要重定向的请求if (REDIRECT REDIRECT){while (win ! win.top){win win.top;}win.location.href xhr.getResponseHeader(CONTEXTPATH);}}});$(button).click(function(){$.get(/page/user, function(result){$(div).html(result);});});
/script四、测试“代码地址https://gitee.com/dingwen-gitee/filter-interceptor-study.git1.拦截器测试1.1启动项目访问首页http://localhost:8080/page/index
“由于没有登录直接重定向到了登录页1.2输入用户名密码完成登录调转到用户页“此时在访问首页1.2 退出登录“成功退出后访问为授权的页面也相对会被重定向到登录页1.3 ajax未授权访问测试“点击访问user 由于未登录没有全权访问。在前端进行了页面跳转转到了登录页。2.过滤器测试“可以看到过滤器进行了相对应的处理重写的getParameterValues()也生效了。配合使用HttpServletRequestWrapper OncePerRequestFilter 实现了对request的修改。
往期推荐
Spring为什么建议构造器注入11个小技巧玩转Spring超级详细的Spring Boot 注解总结