[Spring MVC]@ControllerAdvice注解的用法

简介

昨天学习@ControllerAdvice注解时,很可惜Spring MVC中文文档对其的描述很简单,难以理解它的用法。通过百度一翻,最后总结了@ControllerAdvice的以下几种用法:

  1. 全局异常处理
  2. 全局数据绑定
  3. 全局数据预处理

文档对其的描述是:
@ControllerAdvice是一个组件注解,它使得其实现类能够被classpath扫描自动发现。若应用是通过MVC命令空间或MVC Java编程方式配置,那么该特性默认是自动开启的。
注解@ControllerAdvice的类可以拥有@ExceptionHandler、@InitBinder或@ModelAttribute注解的方法,并且这些方法会被应用至控制器类层次的所有@RequestMapping方法上。

所以,在使用@ControllerAdvice注解时,应该在dispatcherservlet配置文件中指定其路径。例如(该注解类放在org.spring包下):




全局异常处理

控制器

package org.spring;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {
     @RequestMapping(path = "/hello")
      public String execute()
              throws Exception {
          throw new Exception("抛出异常啦");
      }
}

@ControllerAdvive注解类

package org.spring;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class Advice {
    @ExceptionHandler(Exception.class)
    public void test(Exception e) {
        System.out.println(e.getMessage());
    }
}

这里的Advice是全局处理器,test是全局异常处理方法,当控制器抛出异常时,test方法将会被调用,同时可以传入抛出的异常,获取其中定义的错误信息。

全局数据绑定

@ControllerAdvive注解类

package org.spring;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;

@ControllerAdvice
public class Advice {

    @ModelAttribute("name")
    public String test() {
        return "huanghaifeng";
    }

}

控制器

package org.spring;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
 public class HelloController {

        @RequestMapping(path = "/hello")
        public String execute(ModelMap model){
            return model.getAttribute("name").toString();
        }
}


@RequestMapping注解方法execute执行前,先会执行@ControllerAdvice注解的类里的test方法,把数据填充到model中,然后可以在execute方法调用model的相应方法取出。

全局数据预处理

控制器

package org.spring;

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @RequestMapping(path = "/hello")
    public String execute(@ModelAttribute("a") person p) {
        return p.name;
    }
}

class person {

    public person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String name;
}


@ControllerAdvive注解类

package org.spring;

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;

@ControllerAdvice
public class Advice {
    @InitBinder("a")
    public void a(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("a.");
    }

    @ModelAttribute("name")
    public String test() {
        return "huanghaifeng";
    }

}

http://localhost/hello?a.name=12xh
后话

当往@ControllerAdvice注解添加参数,可以指定@ControllerAdvice应用的范围。如,

// Target all Controllers annotated with @RestController
@ControllerAdvice(annotations = RestController.class)
public class AnnotationAdvice {}

指定作用域为@RestController注解的控制器

// Target all Controllers within specific packages
@ControllerAdvice("org.example.controllers")
public class BasePackageAdvice {}

作用域为指定的包内的控制器

// Target all Controllers assignable to specific classes
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class AssignableTypesAdvice {}

直接指定作用域为控制器类型

总结

@ControllerAdvice注解实际上是一个增强了@Controller功能的注解,可以把一些控制器共有的处理,解离出去,优化程序。

你可能感兴趣的:(Spring)