springboot 2.x filters
1. What is springboot 2.x filter
- Similar to a ticket inspector, checks the tickets of tourists
2. Filters in springboot
ApplicationContextHeaderFilter
OrderedCharacterEncodingFilter
OrderedFormContentFilter
OrderedRequestContextFilter
3. Priority of filters
- Higher values are interpreted as lower priority
4. Customize the Filter to avoid the same priority as the default Filter, otherwise it will conflict
- There are two ways to register Filter configuration
- bean FilterRegistrationBean
- Servlet 3.0 webFilter
5. Use the annotations of the new version of servlet 3.0 to develop custom Filters
- Add the annotation @ServletComponentScan to the startup class to scan
- Create a new Filter class, implements Filter, and implement the corresponding interface
- @WebFilter marks a class as filter, which is scanned by spring
- urlPatterns: interception rules, support regular, urlPatterns is the path to filter, filterName is the name of the filter
- Control the method call of chain.doFilter to realize whether to release
- No release, web application resp.sendRedirect("/index.html") or return json string
Scope of use: permission control, user login status control
5.1 Add the annotation @ServletComponentScan to the startup class
@SpringBootApplication //标记此类为springboot 应用
@ServletComponentScan
public class MavenDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MavenDemoApplication.class, args);
}
}
5.2 Create a new filter package and create a Filter class in the package
5.3 The Filter interface is implemented in the class, and the class is marked as @WebFilter, urlPatterns is the filtered path (filters all paths under /api/v1/pri/), and filterName is the name of the filter (login filter)
5.4 Override 3 methods in the class implementing the interface
public void init(FilterConfig filterConfig) throws ServletException {}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {}
public void destroy() {}
The above three methods are all used when the class is loaded, initialization-filtering-destroy, the filtering process occurs in the second filtering
. The code in the filtering process:
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤开始");
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse rep = (HttpServletResponse) servletResponse;
String token =req.getHeader("token"); //从headers中得到token
if (StringUtils.isEmpty(token)){
// 如果header里面没有token时,从请求的参数里面拿token
token = req.getParameter("token");
}
if (!StringUtils.isEmpty(token)){
//如果还为空,直接返回json字符串或跳转index页面
// 判断token是否合法
User user = UserServiceImpl.sessionMap.get(token); //在登录时在sessionMap里存了token,通过token取出user,若为空则未登录,若不为空则显示正确
if(user !=null){
filterChain.doFilter(servletRequest,servletResponse);
}else{
JsonData jsonData = JsonData.buildError("登录失败,token无效",-2);
String jsonStr = objectMapper.writeValueAsString(jsonData); //json转字符
renderJson(rep,jsonStr);
}
}else {
JsonData jsonData = JsonData.buildError("登录失败,token无效",-3);
String jsonStr = objectMapper.writeValueAsString(jsonData);
renderJson(rep,jsonStr);
}
}
private void renderJson(HttpServletResponse response,String json){
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
try(PrintWriter writer=response.getWriter()){
writer.print(json);
}catch (Exception e){
e.printStackTrace();
}
}
springboot listener
Listener:
Application startup listener, session listener, request listener
effect:
- ServletContextListener application startup listener
- HttpSessionListener session listener
- ServletRequestListener request listener
Common listeners
ServletContextListener、HttpSessionListener、ServletRequestListener)
Code:
@WebListener
public class CustomSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("会话监听已开启");
//HttpSessionListener.super.sessionCreated(se);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("会话监听已销毁");
//HttpSessionListener.super.sessionDestroyed(se);
}
}
SpringBoot2.X interceptor
1. Interceptor:
Basically similar to filter usage
2. Steps to use SpringBoot2.X interceptor:
- 2.1 Create a class (such as: CustomWebConfigurer class) to implement the WebMvcConfigurer interface Interceptor configuration class
- 2.2 Annotate @COnfiguration on the class
- 2.3 Override the addInterceptors method in the class, and add multiple custom interceptors to the method
- 2.4 Custom Interceptors
- preHandle: Before calling a method of Controller
- postHandle: Called after the Controller, before the view is rendered, if an
exception occurs in the Controller, this method will not be executed - afterCompletion: Regardless of whether there is an exception, this afterCompletion will be called for resource
cleanup
Interceptor configuration class code:
/**
* 拦截器配置类
*/
@Configuration
public class CustomWebConfigurer implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getLoginInterceptor()).addPathPatterns("/api/v1/pri/**");
//可添加多个拦截器
registry.addInterceptor(new TwoLoginIntercepter()).addPathPatterns("/api/v1/pri/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
@Bean
public LoginIntercepter getLoginInterceptor(){
return new LoginIntercepter();
}
}
Interceptor implementation class code:
public class LoginIntercepter implements HandlerInterceptor {
private static final ObjectMapper objectMapper = new ObjectMapper();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("LoginIntercepter preHandle...");
String token =request.getHeader("token"); //从headers中得到token
if (StringUtils.isEmpty(token)){
token = request.getParameter("token");
}
if (!StringUtils.isEmpty(token)){
// 判断token是否合法
User user = UserServiceImpl.sessionMap.get(token);
if(user !=null){
return true;
}else{
JsonData jsonData = JsonData.buildError("登录失败,token无效",-2);
String jsonStr = objectMapper.writeValueAsString(jsonData);
renderJson(response,jsonStr);
return false;
}
}else {
JsonData jsonData =JsonData.buildError("未登录",-3);
String jsonStr = objectMapper.writeValueAsString(jsonData);
renderJson(response,jsonStr);
return false;
}
//return HandlerInterceptor.super.preHandle(request, response, handler);
}
private void renderJson(HttpServletResponse response,String json){
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
try(PrintWriter writer=response.getWriter()){
writer.print(json);
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("LoginIntercepter postHandle...");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("LoginIntercepter afterCompletion...");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
Common problems with interceptors not working:
- Whether to add @Configuration
- Is there a problem with the interception path ** and *
- The final path of the interceptor must be /** if it is a directory, it is /*/
The difference between Filter and Filter
- Both Filter and Interceptor are the embodiment of AOP programming ideas, and the functions can basically be realized
- The interceptor is more powerful, and it can do everything that Filter can do
- Filter only works before and after Servlet, while Interceptor is deep enough before and after methods, before and after exceptions are thrown, etc.
- The filter depends on the servlet container, that is, the web application, while the interceptor does not depend on the servlet container, so it can run in
a variety of environments. - During the life cycle of the interface call, the Interceptor can be called multiple times, while the Filter can only be called once when the container is initialized
. - Execution order of Filter and Interceptor Before filtering -> before intercepting -> action execution -> after intercepting -> after filtering
How to configure not to block certain paths?
registry.addInterceptor(new
LoginIntercepter()).addPathPatterns("/api/v1/pri/**")
//Configure not to intercept certain paths, such as static resources.excludePathPatterns
("/ /*.html","/ /*.js");