Spring mvc中@ModelAttribute和@ControllerAdvice使用

@ModelAttribute从代码看,可以在方法或方法参数上注解。方法为controller类中的方法。可以是不带@RequestMapping方法。

注解在方法上

    @ModelAttribute
    public Account addAccount(@RequestParam String uid) {
        return accountManager.findAccount(uid);
    }
    
    @ModelAttribute
    public void populateModel(@RequestParam String uid, Model model) {
        model.addAttribute(accountManager.findAccount(uid));
        // add more ...
    }

上面两种写法效果相同,都是将Account暴露到model中,@ModelAttribute 注解的方法只能是@Contrller标注的类或父子类中,每次调用@RequestMapping方法之前都会先调用@ModelAttribute,一般用于获取公共数据,如获取当前用户信息。

注解在方法参数上

public String processSubmit(@ModelAttribute("pet") Pet pet) { 
    
}

如果model中不存在该数据,则会实例化参数,然后添加到model中(省去了手动添加的步骤)。比如示例方法中,如果model中不存在"pet"名称的实例,则会创建一个同名的实例放到model中。model中"pet"来源

  • 可能来自于@SessionAttributes
  • 可能来自于同Contrller类中的@ModelAttribute方法,如上节addAccount方法
@@RequestMapping(path = "/accounts/update/{uid}", method = RequestMethod.PUT)
public String processSubmit(@ModelAttribute("account") Account account) {   }
  • 可能来自于URL模板变量
@RequestMapping(path = "/accounts/{uid}", method = RequestMethod.GET)
public String save(@ModelAttribute("uid") String uid) {  }
  • 可能来自默认构造器实例

注解可配置项

  1. name:表示在model中的名称,如果不配置默认名称根据参数类型和返回值类型确定
protected final void addReturnValueAsModelAttribute(Method handlerMethod, Class handlerType,
            Object returnValue, ExtendedModelMap implicitModel) {

        ModelAttribute attr = AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class);
        String attrName = (attr != null ? attr.value() : "");
        if ("".equals(attrName)) {
            Class resolvedType = GenericTypeResolver.resolveReturnType(handlerMethod, handlerType);
            attrName = Conventions.getVariableNameForReturnType(handlerMethod, resolvedType, returnValue);
        }
        implicitModel.addAttribute(attrName, returnValue);
    }

ControllerAdvice 注解

@ModelAttribute一般解决同一个Controller中共性问题(如果放在一个公共的Contrller父类,也可以解决多Controller间共性问题),@ControllerAdvice主要解决多Contrller中的共性问题,如公共的数据,全局异常处理,全局入参出参转换等。可包含@ExceptionHandler,@InitBinder,@ModelAttribute注解的方法,这些方法默认将对所有Contrller的@RequestMapping方法启用(可通过@ControllerAdvice属性值限制范围)

属性值

basePackages、basePackageClasses、assignableTypes、annotations:限定作用范围,可配置各种类型

//包路径限定
String[] basePackages() default {};
//包路径解析类
Class[] basePackageClasses() default {};
//直接配置Controller类或接口,如{UserController.class,ControllerInterface.class}
Class[] assignableTypes() default {};
//配置指定注解标注的类,如{RestController.class,Controller.class}
Class[] annotations() default {};

InitBinder 注解

初始化数据类型绑定

@Controller
public class MyFormController {

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

    // ...
}

@Controller
public class MyFormController {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
    }

    //
}

JsonView 注解

jackson包下的实现,可在方法、成员变量、方法参数和注解类上使用。

@PostMapping("/get1")
@JsonView(WithoutPasswordView.class)
public User createUser(){  
    return new User("eric", "7!jd#h23",23);
}

@PostMapping("/get2")
@JsonView(WithPasswordView.class)
public User createUser(){ 
    return new User("eric", "7!jd#h23",23);
}

public class User {

    public interface WithoutPasswordView {};
    public interface WithPasswordView extends WithoutPasswordView {};

    private String username;
    private String password;
    private Integer age;

    public User() {
    }

    public User(String username, String password,Integer age) {
        this.username = username;
        this.password = password;
        this.age = age;
    }

    @JsonView(WithoutPasswordView.class)
    public String getUsername() {
        return this.username;
    }
    
    @JsonView(WithoutPasswordView.class)
    public Integer getAge() {
        return this.username;
    }

    @JsonView(WithPasswordView.class)
    public String getPassword() {
        return this.password;
    }
}

请求/get1 返回 {"username":"eric","age":23}
请求/get2 返回 {"username":"eric","age":23,"password":"7!jd#h23"}
实现了根据不同接口需要返回指定数据,也可以在方法入参使用@JsonView(WithPasswordView.class)注解,作用类似

你可能感兴趣的:(Spring mvc中@ModelAttribute和@ControllerAdvice使用)