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

  • 相关阅读:
    android 中文 api (43) —— Chronometer
    SVN客户端清除密码
    Android 中文 API (35) —— ImageSwitcher
    Android 中文API (46) —— SimpleAdapter
    Android 中文 API (28) —— CheckedTextView
    Android 中文 API (36) —— Toast
    Android 中文 API (29) —— CompoundButton
    android 中文 API (41) —— RatingBar.OnRatingBarChangeListener
    Android 中文 API (30) —— CompoundButton.OnCheckedChangeListener
    Android 中文 API (24) —— MultiAutoCompleteTextView.CommaTokenizer
  • 原文地址:https://www.cnblogs.com/yxth/p/10870874.html
Copyright © 2011-2022 走看看