@Controller:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
@RestController:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
* @since 4.0.1
*/
@AliasFor(annotation = Controller.class)
String value() default "";
}
说明
@Component注解源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
String value() default "";
}
加了@Component注解,表明这是一个逻辑组件,告知Spring要为它创建bean。相当于xml配置文件中的 < bean id="" class=""/>的作用。
@AliasFor注解是一个用于声明注解属性别名的注解,源码如下:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface AliasFor {
/**
* Alias for {@link #attribute}.
* <p>Intended to be used instead of {@link #attribute} when {@link #annotation}
* is not declared — for example: {@code @AliasFor("value")} instead of
* {@code @AliasFor(attribute = "value")}.
*/
@AliasFor("attribute")
String value() default "";
/**
* The name of the attribute that <em>this</em> attribute is an alias for.
* @see #value
*/
@AliasFor("value")
String attribute() default "";
/**
* The type of annotation in which the aliased {@link #attribute} is declared.
* <p>Defaults to {@link Annotation}, implying that the aliased attribute is
* declared in the same annotation as <em>this</em> attribute.
*/
Class<? extends Annotation> annotation() default Annotation.class;
}
@Controller中的@AliasFor(annotation = Component.class)说明@Controller是Component的一个别名,本质上还是一个Component,正如注释中所说“to be turned into a Spring bean in case of an autodetected component.”,可以被扫描成一个bean。
同理,@RestController中的@AliasFor(annotation = Controller.class)说明@RestController是Controller的一个别名,是一个Controller,再本质一点说,是个Component,是个Spring bean。
@ResponseBody注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {
}
提到@ResponseBody注解,就不得不提一个名词:表述性状态转移(Representational State Transfer,REST)。
什么是表述性状态转移呢?拆开来看:
表述性.
REST资源实际上可以用各种形式来表述,包括JSON、XML、HTML等;
状态:
使用TEST的时候,我们更关注资源的状态而不是对资源采取的行为;
转移:
以某种形式(例如JSON)从一个应用转换到另一个应用,例如从服务器到客户端。
简单讲,REST就是将资源的状态以最适合客户端或者服务器的形式从服务器转移到客户端(或者反过来)。
在Spring 4.0版本中,Spring支持借助@ResponseBody注解和各种HttpMethodConverter,替换基于视图的渲染方式,实现对REST的支持。当然Spring对REST的支持远不止这一种方式。
@ResponseBody注解告知Spring,要将返回的对象作为资源发送给客户端。
这个过程跳过正常的模型/视图流程中视图解析的过程,而是使用Spring自带的各种Http消息转换器将控制器产生的数据转换为客户端需要的表述形式。
如果客户端请求头的Accept表明他能接受“application/json”,并且Jackson JSON在类路径下面,那么处理方法返回的对象将交给MappingJacksonHTTPMessageConverter,并由他转换为JSON返回给客户端;
如果客户端想要“text/html”格式,那么Jaxb2RootElementHttpMessageConverter将会为客户端产生XML响应。
当处理请求时候,@ResponseBody和@RequestBody是启用消息转换的一种简介和强大方式。但是,如果控制器里面的每个方法都需要信息转换功能的话,那么这些注解就会带有一定程度的重复性。
所以,Spring 4.0引入了@RestController注解,如果在控制器类上面使用@RestController注解,我们不必再为每个方法添加@ResponseBody注解,因为Spring会为该控制器下面的所有方法应用消息转换功能。这也是这个Controller之所以叫RestController的原因,正所谓见名知意。