zoukankan      html  css  js  c++  java
  • Spring boot--控制器增强

    在Spring3.2中,新增了@ControllerAdvice注解。关于这个注解的官方说明https://docs.spring.io/spring-framework/docs/5.0.0.M1/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html

    我们可以根据字面意思将这个注解理解为Controller的Advice(在spring aop中,Advice被翻译为“增强”)。

    在这个控制器的增强处理中,spring提供了三个注解,来帮助我们对Controller进行增强的操作:

    @ExceptionHandler:异常处理器、@InitBinder:初始参数绑定器、@ModelAttribute(模型参数)。

    @ControllerAdvice

    先来看下@ControllerAdvice的内容,这个注解是使用在Class上,里面有几个参数可以指定basePackages,但由于这个注解只是对Controller的增强,因此只对指定包下的Controller生效(如果在dao或service包中对异常上抛,也是可以抛出到Controller层,并通过搭配该注解进行捕获异常)。

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface ControllerAdvice {
        @AliasFor("basePackages")
        String[] value() default {};
    
        @AliasFor("value")
        String[] basePackages() default {};
    
        Class<?>[] basePackageClasses() default {};
    
        Class<?>[] assignableTypes() default {};
    
        Class<? extends Annotation>[] annotations() default {};
    }

    @ExceptionHandler

    @ExceptionHandler:这个注解是使用在方法上,可以处理指定的异常。假如异常不在这个范围内,则不会被捕获,可以定义多个不同的异常处理器用来分别处理不同的异常。

    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ExceptionHandler {
        Class<? extends Throwable>[] value() default {};
    }

    我们来测试一下@ExceptionHandler

    定义一个全局异常处理器,里面指定了两个异常的捕获和处理,一个是IAE,一个是NPE。

    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        @ExceptionHandler(value = IllegalArgumentException.class) //指定异常只处理IAE,也可以指定为Throwable类,可以处理所有的异常。
        @ResponseBody //这里添加ResponseBody是为了直接返回字符串到前端,否则会如同Controller一样,将返回的字符串作为视图名处理,向视图发起请求。
        public String handler(Exception exception) {
            System.out.println("抓住异常,异常原因:");
            System.out.println(exception.getMessage());
            return "IllegalArgumentException";
        }
    
        @ExceptionHandler(value = NullPointerException.class)
        @ResponseBody
        public String handler2(Exception exception) {
            System.out.println("抓住异常,异常原因:");
            System.out.println(exception.getMessage());
            return "NullPointerException";
        }
    
    }

    然后我们定义一个Controller,里面会抛出上面的两种异常

        @GetMapping("users/{id}")
        public String getUser(@PathVariable("id") String id) throws Exception {
            System.out.println("接收到请求[/users/" + id + "]");
            if (id.equals("error")) {
                throw new IllegalArgumentException("参数错误!");
            } else if (id.equals("null")) {
                throw new NullPointerException("id不能为null!");
            }
            return "testUser";
        }

    启动项目,分别输入参数为error和null的请求,查看控制台打印数据:

    接收到请求[/users/error]
    抓住异常,异常原因:
    参数错误!
    
    接收到请求[/users/error]
    抓住异常,异常原因:
    id不能为null!

    如果我们在controller里面再抛出一个其他类型的异常,则会直接返回到前端,而不是被交给异常处理器处理。

    @InitBinder

    这个注解用来对从前端传入的参数进行功能辅助。

    具体的辅助功能有很多种。比如我们传了一个String类型的"2019-05-05",但是我们在controller要用Date来获取,默认情况下是会抛出非法参数异常,如下:

    因此这个时候需要我们在@InitBinder中配置一个自定义日期格式,如下:

        @InitBinder
        public void globalInitBinder(WebDataBinder binder) {
            binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
        }

    这个注解关键的重点在于它的参数WebDataBinder中配置的信息,除了上面的添加自定义格式外,还可以注册其他的类型,如将参数自动存储在Map中。

        @InitBinder
        public void globalInitBinder(WebDataBinder binder) {
            binder.registerCustomEditor(Integer.class, new CustomMapEditor(HashMap.class));
        }

    @ModelAttribute

    该注解用来在Controller接收参数之前对数据模型进行处理,可以添加或删除相关的数据,比如我们在@ModelAttrbute中配置两个数据name和age

        @ModelAttribute
        public void model(Model model) {
            model.addAttribute("name", "yxf");
            model.addAttribute("age", 12);
        }

    然后在Controller的方法中进行配置

        @GetMapping("users/login")
        public String test(@ModelAttribute("name")String name, @ModelAttribute("age") int age) {
            System.out.println("Name="+name + ";Age="+age);
            return "index";
        }

    配置完成后运行启动类,输入路径"/users/login"不带任何参数。

    控制台照样会打印结果:Name=yxf;Age=12

  • 相关阅读:
    mysql 使用SUM()函数查询时,如果没有任何记录的时候 返回的结果为null
    不重复的有序集合,TreeSet的用法
    spring+springMVC+mybatis项目中 多数据源的配置
    程序的位置和功能划分
    团队合作-如何避免JS冲突
    CSS的常见问题
    函数传参的应用--修改文本的值
    应用自定义属性、索引值实现带略缩图的图片轮播
    PC和手机的区别就是各种各样的屏幕,响应式布局来适应屏幕
    CSS3动画@keyframes
  • 原文地址:https://www.cnblogs.com/yxth/p/10870874.html
Copyright © 2011-2022 走看看