preface
Filter, Interceptor, Resolver and Aop are technologies often used in our application development. In this section, we will introduce their usage and application scenarios.
text
filter
- Filter is a means of preprocessing web resources that depends on the existence of servlet. It does not depend on the start of spring container. It is an independent web resource preprocessor. It can uniformly intercept and filter dynamic and static resources. The unified interception function of the filter is useful in spring security to realize the control of access rights and resources. It is a coarse-grained resource access manager, which is mainly used to realize some functions such as unified coding setting, user access control and so on.
- Use steps
① Create a filter and integrate the filter to implement its interface. The init() method will only be executed once when the project is started. The doFilter () method is the specific processing process of the interceptor for resources, and the destroy () method is executed once when the project is destroyed.
package com.yundi.atp.platform.filter; import lombok.extern.slf4j.Slf4j; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @Author: Bei Mingming * @Description: Filters: setting codes * Priority: Filter > interceptor > AOP section * Particle size: fi lt er < interceptor < AOP section * @Date: 2022/1/25 18:33 * @Version: 1.0.0 */ @Slf4j public class ParamFilter implements Filter { @Override public void init(FilterConfig filterConfig) { log.info("[Filter] init It is executed only once during initialization"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //Set code HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); //Record the time spent on the request long startTime = System.currentTimeMillis(); filterChain.doFilter(servletRequest, servletResponse); log.info("[Filter] spend total time:{}ms", System.currentTimeMillis() - startTime); } @Override public void destroy() { log.info("[Filter] destroy It will only be executed once when it is destroyed"); } }
② Register the filter in the FilterRegistrationBean instance
package com.yundi.atp.platform.config; import com.yundi.atp.platform.filter.ParamFilter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @Author: Bei Mingming * @Description: Filter registration: Servlet container level filter * @Date: 2022/1/25 18:38 * @Version: 1.0.0 */ @Configuration public class FilterConfiguration { @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new ParamFilter()); registration.addUrlPatterns("/*"); registration.setName("paramFilter"); // Sets the order in which filters are called registration.setOrder(1); return registration; } }
Interceptor
- Interceptor is one of the processing methods of web request resources in spring MVC. Interceptor can intercept dynamic resources. It is mainly used for login authentication, token verification, program execution time statistics and so on. It is a preprocessing method of application requests in dispatcher servlet. The spring container instance can be obtained to realize the business processing of interception results.
- Use steps
① Create an auth annotation to realize the interception and release of the controller method, and release with auth annotation
package com.yundi.atp.platform.annotation; import java.lang.annotation.*; /** * @Author: Bei Mingming * @Description: Authorization note * @Date: 2022/1/25 16:30 * @Version: 1.0.0 */ @Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface Auth { }
② create interceptor AuthHandlerInterceptor
package com.yundi.atp.platform.interceptor; import com.yundi.atp.platform.annotation.Auth; import com.yundi.atp.platform.module.sys.service.UserService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.core.NamedThreadLocal; import org.springframework.stereotype.Component; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @Author: Bei Mingming * @Description: Authentication through interceptor * @Date: 2022/1/25 16:53 * @Version: 1.0.0 */ @Slf4j @Component public class AuthHandlerInterceptor implements HandlerInterceptor { private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("StopWatch-StartTime"); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { //Inject service UserService userService = this.getBean(UserService.class, request); log.info("injection service:" + userService); //Set current time startTimeThreadLocal.set(System.currentTimeMillis()); log.info("[Interceptor method Controller Before method execution..."); if ((handler instanceof HandlerMethod) && (((HandlerMethod) handler).getMethodAnnotation(Auth.class) != null)) { return true; } return verifyToken(request); } private boolean verifyToken(HttpServletRequest request) { String token = request.getHeader("token"); if (StringUtils.isNotBlank(token)) { //token is parsed by todo, and false is not returned } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { log.info("[Interceptor method Controller After the method is executed..."); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { log.info("[Interceptor view Execute after the view rendering is complete..."); log.info("[Interceptor] spend total time:{}ms", System.currentTimeMillis() - startTimeThreadLocal.get()); } /** * Get container object instance * @param clazz * @param request * @param <T> * @return */ private <T> T getBean(Class<T> clazz, HttpServletRequest request) { WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext()); return applicationContext.getBean(clazz); } }
③ registered interceptor
package com.yundi.atp.platform.config; import com.yundi.atp.platform.interceptor.AuthHandlerInterceptor; import com.yundi.atp.platform.resolver.AuthHandlerMethodArgumentResolver; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; /** * @Author: Bei Mingming * @Description: Add a static resource file, and the external can directly access the address * @Date: 2021/5/18 10:54 * @Version: 1.0.0 */ @Configuration public class MyWebMvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/"); registry.addResourceHandler("/tinymce/**").addResourceLocations("classpath:/tinymce/"); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new AuthHandlerInterceptor()).addPathPatterns("/**").order(1); } @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(new AuthHandlerMethodArgumentResolver()); } }
Parameter parser
- The parameter parser HandlerMethodArgumentResolver parses the parameters in the web request into standard data and binds it to the controller to receive it, which is similar to the @ RequestBody annotation to realize the unified processing of data.
- Use steps
① Create a parameter parser annotation
package com.yundi.atp.platform.annotation; import java.lang.annotation.*; /** * @Author: Bei Mingming * @Description: Authorization note * @Date: 2022/1/25 16:30 * @Version: 1.0.0 */ @Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface Param { }
② create a parameter parser ParamHandlerMethodArgumentResolver
package com.yundi.atp.platform.resolver; import com.yundi.atp.platform.annotation.Param; import lombok.extern.slf4j.Slf4j; import org.springframework.core.MethodParameter; import org.springframework.stereotype.Component; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; import javax.servlet.http.HttpServletRequest; /** * @Author: Bei Mingming * @Description: Parameter parser authentication: its function is to parse request parameters and bind data to Controller input parameters * @Date: 2022/1/25 17:47 * @Version: 1.0.0 */ @Slf4j @Component public class ParamHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter methodParameter) { log.info("[[method parser] parameter parser authentication 2!"); return methodParameter.hasParameterAnnotation(Param.class); } @Override public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) { if (methodParameter.getParameterType().equals(String.class)) { HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class); String token = request.getHeader("token"); return token; } return null; } }
③ Register parameter parser
/* * ****************************************************************************************************************************************** * Copyright (c) 2021 . * All rights reserved. * Project Name: ATP platform * Project Description: application test platform management end * Copyright note: this software is owned by Yundi Technology Co., Ltd. without the formal authorization of Yundi Technology Co., Ltd., no enterprise or individual can obtain, read, install and disseminate any content protected by intellectual property rights involved in this software. * ******************************************************************************************************************************************* */ package com.yundi.atp.platform.config; import com.yundi.atp.platform.interceptor.AuthHandlerInterceptor; import com.yundi.atp.platform.resolver.ParamHandlerMethodArgumentResolver; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; /** * @Author: Bei Mingming * @Description: Add a static resource file, and the external can directly access the address * @Date: 2021/5/18 10:54 * @Version: 1.0.0 */ @Configuration public class MyWebMvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/"); registry.addResourceHandler("/tinymce/**").addResourceLocations("classpath:/tinymce/"); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new AuthHandlerInterceptor()).addPathPatterns("/**").order(1); } @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(new ParamHandlerMethodArgumentResolver()); } }
④ Bind parameter parser to controller
@ApiOperation(value = "Query all user information details test") @GetMapping(value = "/findAllUserInfoTest") public Result findAllUserInfoTest(@Param String id) { return Result.success(id); }
aop section
- aop aspect is one of the important components of spring framework. In the project application, it is mainly used to record the operation log. It can obtain the method level input and output parameters, and can be used as a low granularity web resource processor.
- Use steps
① Create section annotation
package com.yundi.atp.platform.annotation; import java.lang.annotation.*; /** * @Author: Bei Mingming * @Description: Log annotation * @Date: 2022/1/25 16:30 * @Version: 1.0.0 */ @Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface OperationLog { }
② Create log facet OperationLogAspect
package com.yundi.atp.platform.aspect; import com.yundi.atp.platform.annotation.OperationLog; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.context.annotation.Configuration; /** * @Author: Bei Mingming * @Description: Through aspect authentication * @Date: 2022/1/25 16:34 * @Version: 1.0.0 */ @Aspect @Slf4j @Configuration public class OperationLogAspect { /** * Tangent point */ @Pointcut("@annotation(com.yundi.atp.platform.annotation.OperationLog)") public void logPointCut() { } @Around(value = "logPointCut() && @annotation(operationLog)") public void operationLogStore(JoinPoint joinPoint, OperationLog operationLog) { //todo log processing log.info("[Section] this is the use of a section!"); } }
③ Apply
@Auth @OperationLog @ApiOperation(value = "Query all user information details") @GetMapping(value = "/findAllUserInfo") public Result findAllUserInfo() { List<User> userList = userService.findAllUserInfo(); return Result.success(userList); }
epilogue
OK, that's the end of this issue. I'll see you in the next issue...