在Spring框架中,@Controller
和@RestController
注解都用于定义Spring MVC中的控制器,但它们在处理HTTP响应时有一些区别:
@Controller
@Controller
是一个常规的MVC控制器,主要用于返回视图(例如JSP页面)。当使用@Controller
注解时,如果要响应JSON或XML等数据格式,通常会在方法上添加@ResponseBody
注解以指示方法返回的对象应该作为HTTP响应正文直接写入。
示例代码(@Controller)
@Controller
@RequestMapping("/web")
public class WebController {
@RequestMapping(value = "/greeting", method = RequestMethod.GET)
public ModelAndView greeting() {
ModelAndView mav = new ModelAndView("greeting");
mav.addObject("message", "Welcome to Spring MVC!");
return mav; // 返回的是视图名
}
@ResponseBody
@RequestMapping(value = "/data", method = RequestMethod.GET)
public Map<String, String> data() {
Map<String, String> data = new HashMap<>();
data.put("key", "value");
return data; // 返回的数据将自动转换为JSON
}
}
在这个示例中,greeting
方法返回一个ModelAndView
对象,该对象将由视图解析器处理以决定最终的视图。而data
方法由于有@ResponseBody
注解,返回的Map将被转换为JSON格式的响应内容。
@RestController
@RestController
是Spring 4.0引入的注解,它是一个组合注解,相当于@Controller
和每个方法上的@ResponseBody
的组合。当一个控制器类被@RestController
注解时,该类中的所有方法都默认使用@ResponseBody
注解。这非常适合创建RESTful服务,因为它简化了返回JSON或XML的代码。
示例代码(@RestController)
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/users")
public List<String> listUsers() {
return Arrays.asList("user1", "user2", "user3"); // 直接返回数据,会自动转换成JSON
}
}
在这里,listUsers
方法返回一个字符串列表,由于类级别上有@RestController
注解,这个字符串列表会自动转换为JSON数组作为HTTP响应。
源码分析
在Spring MVC的底层实现中,@Controller
和@RestController
都是通过RequestHandler
机制来处理请求。@RestController
实际上就是一个便利的注解,它组合了@Controller
和@ResponseBody
,它的实现可以通过查看Spring的@RestController
注解源码看出这一点。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
@AliasFor(annotation = Controller.class)
String value() default "";
}
如你所见,@RestController
的定义中包含了@Controller
和@ResponseBody
,这意味着它继承了两者的特性。
总结
- 使用
@Controller
时,方法默认不会将返回值作为响应正文,除非方法上加了@ResponseBody
注解。 - 使用
@RestController
时,类中所有方法默认都会将返回值作为响应正文。 - 选择使用
@Controller
或@RestController
取决于你是否想为整个控制器类的方法自动应用@ResponseBody
效果,即是否打算编写主要返回JSON或XML的REST