(十六)ATP应用测试平台——java应用中的过滤器Filter、拦截器Interceptor、参数解析器Resolver、Aop切面,你会了吗?

前言

过滤器Filter、拦截器Interceptor、参数解析器Resolver、Aop切面是我们应用开发中经常使用到的技术,到底该如何使用这些web附属功能, 本小节我们就分别介绍一下其各自的用法及其应用场景。

正文

过滤器

  • 过滤器Filter是依赖于servlet存在的一种对web资源预处理的一种手段,不依赖于spring容器启动,是一种独立的web资源预处理器。能够对动静态资源统一拦截,统一过滤,springsecurity中就有用到过滤器的统一拦截功能,实现访问权限资源的控制。其是一种粗粒度的资源访问管理器,主要用来实现一些统一编码设置、用户访问控制等功能。
  • 使用步骤

①创建一个过滤器并集成filter实现其接口,init()方法只会在项目启动时执行一次,doFilter()方法是拦截器具体实现对资源的处理过程,destroy()方法是在项目销毁时执行一次。

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: 北溟溟
 * @Description: 过滤器:设置编码
 * 优先级:过滤器>拦截器>AOP切面
 * 粒度:过滤器<拦截器<AOP切面
 * @Date: 2022/1/25 18:33
 * @Version: 1.0.0
 */
@Slf4j
public class ParamFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) {
        log.info("【过滤器】init只会初始化时执行一次");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //设置编码
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        //记录请求花费的时间
        long startTime = System.currentTimeMillis();
        filterChain.doFilter(servletRequest, servletResponse);
        log.info("【过滤器】spend total time:{}ms", System.currentTimeMillis() - startTime);
    }

    @Override
    public void destroy() {
        log.info("【过滤器】destroy只会销毁时执行一次");
    }
}

②将filter注册到FilterRegistrationBean实例中

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: 北溟溟
 * @Description: 过滤器注册:Servlet容器级别的过滤器
 * @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");
        // 设置过滤器被调用的顺序
        registration.setOrder(1);
        return registration;
    }
}

拦截器

  • 拦截器是springmvc中对于web请求资源的处理手段之一,拦截器可以实现动态资源的拦截处理,主要用于登录认证,token校验,程序执行时间统计等等,是DispatcherServlet中对应用请求的预处理手段。能够获取到spring容器实例,实现拦截结果业务处理。
  • 使用步骤

①创建一个auth注解,实现controller方法的拦截与放行,有auth注解的放行

package com.yundi.atp.platform.annotation;

import java.lang.annotation.*;

/**
 * @Author: 北溟溟
 * @Description: 授权注解
 * @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 {
}

 ②创建拦截器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: 北溟溟
 * @Description: 通过拦截器鉴权
 * @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) {
        //注入service
        UserService userService = this.getBean(UserService.class, request);
        log.info("注入service:" + userService);
        //设置当前时间
        startTimeThreadLocal.set(System.currentTimeMillis());
        log.info("【拦截器】方法在Controller方法执行前。。。");
        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)) {
            //todo 解析token,不通过返回false

        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        log.info("【拦截器】方法在Controller方法执行结束后执行。。。");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        log.info("【拦截器】在view视图渲染完成后执行。。。");
        log.info("【拦截器】spend total time:{}ms", System.currentTimeMillis() - startTimeThreadLocal.get());
    }

    /**
     * 获取容器对象实例
     * @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);
    }
}

 ③注册拦截器

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: 北溟溟
 * @Description: 添加静态资源文件,外部可以直接访问地址
 * @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());
    }
}

参数解析器

  • 参数解析器HandlerMethodArgumentResolver将web请求中的参数解析为标准的数据并绑定到controller中接收,类似于@RequestBody注解,实现数据的统一处理。
  • 使用步骤

①创建一个参数解析器注解

package com.yundi.atp.platform.annotation;

import java.lang.annotation.*;

/**
 * @Author: 北溟溟
 * @Description: 授权注解
 * @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 {
}

 ②创建一个参数解析器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: 北溟溟
 * @Description: 参数解析器鉴权:其功能就是解析request请求参数并绑定数据到Controller的入参上
 * @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("【方法解析器】参数解析器鉴权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;
    }
}

③注册参数解析器

/*
 * ******************************************************************************************************************************************
 * Copyright (c) 2021 .
 * All rights reserved.
 * 项目名称:atp-platform
 * 项目描述:应用测试平台管理端
 * 版权说明:本软件属云嘀科技有限公司所有,在未获得云嘀科技有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 * *******************************************************************************************************************************************
 */
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: 北溟溟
 * @Description: 添加静态资源文件,外部可以直接访问地址
 * @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());
    }
}

④绑定参数解析器到controller

 @ApiOperation(value = "查询全部用户信息详情测试")
 @GetMapping(value = "/findAllUserInfoTest")
 public Result findAllUserInfoTest(@Param String id) {
     return Result.success(id);
 }

aop切面

  • aop切面是spring框架的重要组件之一,在项目应用中我们主要用来做操作日志的记录,它能够获取到方法级别的入参、出参,可用作低粒度级别的web资源处理器。
  • 使用步骤

①创建切面注解

package com.yundi.atp.platform.annotation;

import java.lang.annotation.*;

/**
 * @Author: 北溟溟
 * @Description: 日志注解
 * @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 {
}

②创建日志切面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: 北溟溟
 * @Description: 通过切面鉴权
 * @Date: 2022/1/25 16:34
 * @Version: 1.0.0
 */
@Aspect
@Slf4j
@Configuration
public class OperationLogAspect {
    /**
     * 切点
     */
    @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.info("【切面】这是一个切面的使用!");
    }

}

③ 应用

@Auth
@OperationLog
@ApiOperation(value = "查询全部用户信息详情")
@GetMapping(value = "/findAllUserInfo")
public Result findAllUserInfo() {
	List<User> userList = userService.findAllUserInfo();
	return Result.success(userList);
}    

结语

OK,本期内容到这里就结束了,我们下期见。。。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring拦截器过滤器AOP是Spring框架常用的三种技术,用于实现对请求的处理和控制。它们的作用和使用方式有一些不同,我分别对它们进行简单解释。 1. 过滤器Filter): 过滤器Java Servlet规范提供的一种技术,用于在请求到达Servlet之前或响应返回给客户端之前拦截和处理请求。过滤器可以在Web应用的整个生命周期起作用,对所有请求都生效。常见的应用场景包括:编码转换、身份认证、日志记录等。 2. 拦截器Interceptor): 拦截器是Spring框架提供的一种技术,用于在请求到达Handler(Controller方法)之前或响应返回给客户端之前对请求进行拦截和处理。拦截器只在Spring MVC起作用,用于实现对请求的预处理和后处理。常见的应用场景包括:身份认证、权限控制、日志记录等。 3. AOP(面向切面编程): AOP是一种编程思想,也是Spring框架提供的一种技术。通过AOP,可以将与业务逻辑无关的横切关注点(如日志、事务管理等)从业务逻辑解耦出来,以模块化的方式进行管理。在SpringAOP通常通过动态代理实现,可以在方法执行前、后或抛出异常时进行一些额外的处理。AOP常用于事务管理、日志记录、性能监控等方面。 总结: - 过滤器主要用于在Servlet规范对请求进行拦截和处理。 - 拦截器主要用于在Spring MVC对请求进行拦截和处理。 - AOP主要用于将与业务逻辑无关的横切关注点进行解耦和管理。 希望以上解释能对你有所帮助!如果有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

厉害哥哥吖

您的支持是我创作下去的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值