Java教程

Aop基于注解拦截 和 基于方法拦截,控制器建言,拦截器,过滤器

本文主要是介绍Aop基于注解拦截 和 基于方法拦截,控制器建言,拦截器,过滤器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Aop基于注解拦截 和 基于方法拦截

引用

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency> <!--@Aspect用了这个包-->
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>

基于注解拦截

  • 注解
@Target(ElementType.METHOD) //方法上
@Retention(RetentionPolicy.RUNTIME) //运行的
@Documented //没用 文档
public @interface Action {
    String name();
}
  • 使用注解
@Service
public class AnnotationService {
    @Action(name = "注解式拦截add操作,我是注解的name值")
    public void add() {
        System.out.println("AnnotationService的添加方法被调用了");
    }
}
  • 切面
@Aspect
@Component
public class LogAspect {
    //切点:切这个注解
    @Pointcut("@annotation(com.xin.demoxin.aop.Action)")
    public void annotationPointCut() {
    }

    //这里是先调用主方法,在执行切面的方法
    @After("annotationPointCut()")
    public void after(JoinPoint joinPoint) {
        //原生方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		//获取这个方法
        Method method = signature.getMethod();
        //打印方法名
        System.out.println("\n注解是拦截器的方法是:" + method.getName());
        
		//获取方法上的注解
        Action action = method.getAnnotation(Action.class);
		//打印注解上 自己写的name
        System.out.println("方法上注解的文字是:" + action.name());
    }
}
  • 配置类
@Configuration
@ComponentScan("com.xin.demoxin.aop") //指定扫描哪个包下
@EnableAspectJAutoProxy //开启
public class AopConfig {
}
  • 测试类
    public static void main(String[] args) {
    	//注解上下文。使用配置类
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(AopConfig.class);
		//获得bean
        AnnotationService bean = context.getBean(AnnotationService.class);
		//调用
        bean.add();

    }
  • 结果
AnnotationService的添加方法被调用了 //先调用具体的方法

注解是拦截器的方法是:add //然后走 切面的方法
方法上注解的文字是:注解式拦截add操作,我是注解的name值

基于方法的拦截

  • 写一个普通的类
@Service
public class MethodService {
    public void add() {
        System.out.println("MethodService的添加方法被调用了");
    }
}
  • 在切面类 里增加方法,切这个类
    //切 这个类的 所有方法
    @Before("execution(* com.xin.demoxin.aop.MethodService.*(..))")
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        Method method = signature.getMethod();

        System.out.println("MethodService里将要被调用的方法是:" + method.getName());
    }
  • 测试
        MethodService bean2 = context.getBean(MethodService.class);
        bean2.add();
        
        //结果为

MethodService里将要被调用的方法是:add //这里用的是:@Before。故:先执行切面的方法,
MethodService的添加方法被调用了 

拦截器 Interceptor

统计 请求时长的拦截器

//implements HandlerInterceptor 或继承:HandlerInterceptorAdapter 已经废弃
public class DemoInterceptor implements AsyncHandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        long time = System.currentTimeMillis();

        request.setAttribute("startTime", time);

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

        long startTime = (Long) request.getAttribute("startTime");
        request.removeAttribute("startTime");

        long endTime = System.currentTimeMillis();
        System.out.println("本次请求的时间ms是:" + (endTime - startTime));
        
		//又设置给request了
        request.setAttribute("handlingTime", endTime - startTime);
    }
}

MVC配置

//继承 WebMvcConfigurerAdapter 已过时
@Configuration
@EnableWebMvc
public class MyMvcConfig implements WebMvcConfigurer {

    @Bean
    public DemoInterceptor demoInterceptor() {
        return new DemoInterceptor();
    }

    @Resource
    private DemoInterceptor demoInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(demoInterceptor);
    }
}
@RestController
public class TestController2 {

    @GetMapping("/testOne")
    public String testOne() {
        try {
            Thread.sleep(1000L);
        } catch (Exception e) {

        }
        return "haha";
    }
}
本次请求的时间ms是:1002

ControllerAdvice

@ControllerAdvice
@ExceptionHandler
@InitBinder
@ModelAttribute

编写:控制器建言

@ControllerAdvice
public class ExceptionHandlerAdvice {

    @ModelAttribute
    public void addAttributes(Model model) {
        model.addAttribute("msg", "额外信息");
    }

    @InitBinder
    public void initBinder(WebDataBinder webDataBinder) {
        //过滤ID
        webDataBinder.setDisallowedFields("id");
    }

    @ExceptionHandler(value = Exception.class)
    public ModelAndView exception(Exception e, WebRequest request) {
        //跳转到错误页面,已经不用了吧
        ModelAndView m = new ModelAndView("error");
        m.addObject("errorMessage", e.getMessage());
        return m;
    }
}
    @GetMapping("/testOne2")
    public String testOne2(@ModelAttribute("msg") String msg) {

        System.out.println("请求到了");
        throw new IllegalArgumentException("非常抱歉,参数异常。" + msg);

    }

以前写的一个

    @ResponseBody
    @ExceptionHandler(value = {MethodArgumentNotValidException.class, BindException.class})
    public ResponseEntity<Pesponsibles> methodArgumentNotValidExceptionHandler(Exception e, BindingResult bindingResult) {

        Pesponsibles p = new Pesponsibles();

        // 如果没有参数异常则直接返回错误信息
        if (bindingResult.hasErrors()) {
            //有异常下面处理
        } else {
            //bindingResult没有异常,但是exception有异常
            p.setDefaultMessage(e.getMessage());
            return new ResponseEntity<>(p, HttpStatus.BAD_REQUEST);
        }

        p.setField("bindingResult错误字段");
        //如果包含错误
        if (bindingResult.hasErrors()) {
            //获取到 所有错误
            List<FieldError> fieldErrors = bindingResult.getFieldErrors();

            // 如果有参数异常,则获取default message,并返回
            StringBuilder message = new StringBuilder("提示:");
            //拼接 错误
            fieldErrors.forEach(i -> message.append(i.getDefaultMessage()).append("!"));
            p.setDefaultMessage(message.toString());

            // pesponsibles.setError_msg(fieldErrors);
            return new ResponseEntity<>(p, HttpStatus.BAD_REQUEST);
        }

        return new ResponseEntity<>(p, HttpStatus.BAD_REQUEST);
    }

过滤器

过滤器代码

public class LogCostFilter implements Filter {
    //@Override
    public void init(FilterConfig filterConfig) throws ServletException {

        System.out.println("测试");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        long start = System.currentTimeMillis();
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("Execute cost=" + (System.currentTimeMillis() - start));
    }

    @Override
    public void destroy() {

    }
}

配置类

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean registFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new LogCostFilter());
        registration.addUrlPatterns("/*");
        registration.setName("LogCostFilter");
        registration.setOrder(1);
        return registration;
    }

}
这篇关于Aop基于注解拦截 和 基于方法拦截,控制器建言,拦截器,过滤器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!