spring MVC注解深入研究
@Controller @Service @Controller和 @Component
注册一个action 到spring 上下文中,bean 的ID 默认为类名称开头字母小写。
@Repository、@Service 和@Controller。这 3 个注解和 @Component 是等效的,但是从注解类的命名上,很容易看出这 3 个注解分别和持久层、业务层和控制层(Web 层)相对应。虽然目前这 3 个注解和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用@Repository、@Service 和 @Controller 对分层中的类进行注解,而用 @Component 对那些比较中立的类进行注解。
例:
@Controller public class Apple extends Friut {}
@Autowired
以byType的方式对类成员变量、方法及构造函数进行标注,完成自动装配的工作。Spring 将直接采用 Java 反射机制对 类 中的 私有成员变量进行自动注入。所以对成员变量使用 @Autowired 后,可将它们的getter和setter 方法删除。
例:
public class Boss { @Autowired private Car car; @Autowired private Office office; }
也可以对set方法和构造函数使用@ Autowired注解 ,等同于上文
public class Boss { private Car car; private Office office; @Autowired public void setCar(Car car) { this.car = car; } @Autowired public void setOffice(Office office) { this.office = office; } } public class Boss { private Car car; private Office office; @Autowired public Boss(Car car ,Office office){ this.car = car; this.office = office ; } }
如何使用Autowired 的required参数
@Autowired(required = false) public void setOffice(Office office) { this.office = office; }
一般情况下,使用 @Autowired 的地方都是需要注入 Bean 的,使用了自动注入而又允许不注入的情况一般仅会在开发期或测试期碰到(如为了快速启动 Spring 容器,仅引入一些模块的 Spring 配置文件),所以 @Autowired(required = false) 会很少用到。
@Resource
@Resource 的作用相当于 @Autowired,只不过 @Autowired 按 byType 自动注入,而 @Resource 默认按 byName 自动注入。@Resource 有两个属性是比较重要的,分别是 name 和 type,Spring 将 @Resource 注解的 name 属性解析为 Bean 的名字,而 type 属性则解析为 Bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略。
例:
public class Boss { // 自动注入类型为 Car 的 Bean @Resource private Car car; // 自动注入 bean 名称为 office 的 Bean @Resource(name = "office") private Office office; }
@PostConstruct 和 @PreDestroy
只需要在方法前标注 @PostConstruct 或 @PreDestroy,这些方法就会在 Bean 初始化后或销毁之前被 Spring 容器执行, 常用于对静态变量的处理。
public class Boss { private static Car car = initCar(); @Resource(name = "office") private Office office; @PostConstruct public void initCar(){ System.out.println("postConstruct1"); } @PreDestroy public void preDestroy1(){ System.out.println("preDestroy1"); } }
@RequestMapping
将URL映射到类或方法上。
@RequestMapping(value="/car") public class Car { @RequestMapping(value="/getName") public String myCarName(){ return “audi”; } }
通过http://{ ip:port/上下文}/car/getName 来请求该方法
当它定义在类级别时,标明该控制器处理所有的请求都被映射到 /car路径下。@RequestMapping中可以使用 method 属性标记其所接受的方法类型,如果不指定方法类型的话,可以使用 HTTP GET/POST 方法请求数据,但是一旦指定方法类型,就只能使用该类型获取数据。支持方法共有四种:GET, POST, PUT, DELETE
@RequestMapping(value="/getName", method = RequestMethod.GET) public String getName(String userName) { return userName; }
绑定 @RequestMapping参数
使用 @PathVariable 注解方法参数并将其绑定到URI模板变量的值上
@RequestMapping(value="/departments/{departmentId}/employees/{employeeId}") public String findEmployee( @PathVariable String departmentId, @PathVariable String employeeId){ System.out.println("Find employee with ID: " + employeeId + " from department: " + departmentId); return "someResult"; }
支持正则表达式
@RequestMapping(value="/{textualPart:[a-z-]+}.{numericPart:[\\d]+}") public String regularExpression( @PathVariable String textualPart, @PathVariable String numericPart){ System.out.println("Textual part: " + textualPart + ", numeric part: " + numericPart); return "someResult"; }
@RequestParam
可以把请求参数传递给请求方法
例: http://{ ip:port/上下文}/car/getName?ownerId=5
@RequestMapping(value="/car") public class Car {
@RequestMapping(value="/getName") public String myCarName(@RequestParam("ownerId") int ownerId){ return “audi”; } }
@ModelAttribute
@ModelAttribute有三种用法:
1、注解方法
当它作用在方法上时,标明该方法的目的是添加一个或多个模型属性(model attributes)。该方法支持与@RequestMapping一样的参数类型,但并不能直接映射成请求。controller中的@ModelAttribute方法会在所有@RequestMapping方法调用之前而调用,因此要小心使用。
利用这个特征进行权限验证, index方法执行之前会先执行preRun方法
@Controller @RequestMapping(value="/test") public class PassportController { @ModelAttribute public void preRun() { if(user != “admin”){ throw Exception(“没有权限”); } } @RequestMapping(method=RequestMethod.GET) public String index() { return "login/index"; } }
2、注解方法中的入参
用于将多个请求参数绑定到一个命令对象,将这个对象添加到request作用域,从而简化绑定流程,而且自动暴露为模型数据用于jsp展示时使用
@RequestMapping(value="test") public String test(@ModelAttribute("user") UserModel user){ User.setName(“aaa”); }
此时可以在视图页面使用${user.name}来获取绑定的命令对象的属性
3、注解方法的返回值,效果同上,将返回值添加到request作用域,jsp页面中可以通过${user.name}的方式直接调用,@ModelAttribute 注解的返回值会覆盖@RequestMapping 注解方法中的@ModelAttribute 注解的同名命令对象。
public @ModelAttribute("user2") UserModel test3(@ModelAttribute("user2") UserModel user)
@RequestBody
读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上 ,再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
@ResponseBody
将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
@ExceptionHandler和@ControllerAdvice
@ExceptionHandler 注解到方法上,出现异常时会执行该方法。 @ControllerAdvice 使一个Contoller成为全局的异常处理类,类中用@ExceptionHandler方法注解的方法可以处理所有Controller发生的异常。
@RestController (spring 3.1 以上)
使一个类以Rest风格返回请求数据, 它与@Controller的差别在于使用@Controller标注的类别最后会回传一个String,然后透过viewResolver组装出完整的view page路径后将这个view呈现在前端页面中。而使用 @RestController标注表示此类别最后会回传一个POJO对象而非一个页面,因此也不需要透过viewResolver来帮忙组装回传值。
通过jackson套件,可以将RestController回传的domain对象以JSON或XML格式的方式返回前端。
@RestController public class HelloWorldRestController { @RequestMapping("/hello/{player}") public Message message(@PathVariable String player) { Message msg = new Message(player, "Hello, " + player); return msg; } }
VO字段验证
@AssertFalse
验证的数据类型 :Boolean,boolean
说明 :验证注解的元素值是false
@AssertTrue
验证的数据类型 :Boolean,boolean
说明 :验证注解的元素值是true
@NotNull
验证的数据类型 :任意类型
说明 :验证注解的元素值不是null
@Null
验证的数据类型 :任意类型
说明 :验证注解的元素值是null
@Min(value=值)
验证的数据类型 :BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存储的是数字)子类型
说明 :验证注解的元素值大于等于@Min指定的value值
@Max(value=值)
验证的数据类型 :和@Min要求一样
说明 :验证注解的元素值小于等于@Max指定的value值
@DecimalMin(value=值)
验证的数据类型 :和@Min要求一样
说明 :验证注解的元素值大于等于@ DecimalMin指定的value值
@DecimalMax(value=值)
验证的数据类型 :和@Min要求一样
说明 :验证注解的元素值小于等于@ DecimalMax指定的value值
@Digits(integer=整数位数, fraction=小数位数)
验证的数据类型 :和@Min要求一样
说明 :验证注解的元素值的整数位数和小数位数上限
@Size(min=下限, max=上限)
验证的数据类型 :字符串、Collection、Map、数组等
说明 :验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小
@Past
验证的数据类型 :java.util.Date,java.util.Calendar,Joda Time类库的日期类型
说明 :验证注解的元素值(日期类型)比当前时间早
@Future
验证的数据类型 :与@Past要求一样
说明 :验证注解的元素值(日期类型)比当前时间晚
@NotBlank
验证的数据类型 :CharSequence子类型
说明 :验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的首位空格
@Length(min=下限, max=上限)
验证的数据类型 : CharSequence子类型
说明 :验证注解的元素值长度在min和max区间内
@NotEmpty
验证的数据类型 :CharSequence子类型、Collection、Map、数组
说明 :验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@Range(min=最小值, max=最大值)
验证的数据类型 :BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型
说明 :验证注解的元素值在最小值和最大值之间
@Email(regexp=正则表达式,flag=标志的模式)
验证的数据类型 :CharSequence子类型(如String)
说明 :验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式
@Pattern(regexp=正则表达式,flag=标志的模式)
验证的数据类型 :String,任何CharSequence的子类型
说明 :验证注解的元素值与指定的正则表达式匹配
@Valid
验证的数据类型 :任何非原子类型
说明 :指定递归验证关联的对象;如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证