Difference between spring @Controller
and @RestController
annotation.
Can @Controller
annotation be used for both Web MVC and REST applications?
If yes, how can we differentiate if it is Web MVC or REST application.
@RestController
it is designed to follow the REST architectural design
. As the main purpose of an REST API
it is to provide only data to be processed by another application. Therefore, as explained below you can only send data cannot return a view.
@Controller is used to mark classes as Spring MVC Controller.
@RestController is a convenience annotation that does nothing more than adding the @Controller and @ResponseBody annotations (see: Javadoc)
So the following two controller definitions should do the same
@Controller
@ResponseBody
public class MyController { }
@RestController
public class MyRestController { }
In the code below I'll show you the difference between @controller
@Controller
public class RestClassName{
@RequestMapping(value={"/uri"})
@ResponseBody
public ObjectResponse functionRestName(){
//...
return instance
}
}
and @RestController
@RestController
public class RestClassName{
@RequestMapping(value={"/uri"})
public ObjectResponse functionRestName(){
//...
return instance
}
}
the @ResponseBody
is activated by default. You don't need to add it above the function signature.
If you use @RestController
you cannot return a view (By using Viewresolver
in Spring/springboot) and yes @ResponseBody
is not needed in this case.
If you use @Controller
you can return a view in Spring web MVC.
@RestController
is the combination of @Controller
and @ResponseBody
.
Flow of request in a @Controller
class without using a @ResponseBody
annotation:
https://i.stack.imgur.com/xm7KW.png
@RestController
returns an object as response instead of view.
https://i.stack.imgur.com/wCZrD.png
@RestController
annotated classes are the same as @Controller
but the @ResponseBody
on the handler methods are implied.
Actually, be careful - they are not exactly the same.
If you define any interceptors within your application, they will not apply to Controllers annotated as @RestController
, however they do work with @Controller
annotated controllers.
ie. configuration for the interceptor:
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TemplateMappingInterceptor()).addPathPatterns("/**", "/admin-functions**").excludePathPatterns("/login**");
}
}
and in the declaration of a Spring controller:
@Controller
public class AdminServiceController {...
Will work, however
@RestController
public class AdminServiceController {...
does not end up having the interceptor being associated with it.
@RestController
was introduced in Spring 4x. This annotation is also annotated itself by @Controller
so if it not working like an @Controller
then report this as a bug.
Interceptor
to a @RestController
.
Interceptor
to a @RestController
.
As you can see in Spring documentation (Spring RestController Documentation) Rest Controller annotation is the same as Controller annotation, but assuming that @ResponseBody
is active by default, so all the Java objects are serialized to JSON representation in the response body.
@Controller
returns View
. @RestController
returns ResponseBody
.
THE new @RestController annotation in Spring4+, which marks the class as a controller where every method returns a domain object instead of a view. It’s shorthand for @Controller and @ResponseBody rolled together.
@RestController
was provided since Spring 4.0.1. These controllers indicate that here @RequestMapping methods assume @ResponseBody semantics by default.
In earlier versions the similar functionality could be achieved by using below:
@RequestMapping coupled with @ResponseBody like @RequestMapping(value = "/abc", method = RequestMethod.GET, produces ="application/xml") public @ResponseBody MyBean fetch(){ return new MyBean("hi") }
@XmlRootElement(name = "MyBean") @XmlType(propOrder = {"field2", "field1"}) public class MyBean{ field1 field2 .. //getter, setter }
@ResponseBody is treated as the view here among MVC and it is dispatched directly instead being dispatched from Dispatcher Servlet and the respective converters convert the response in the related format like text/html, application/xml, application/json .
However, the Restcontroller is already coupled with ResponseBody and the respective converters. Secondly, here, since instead of converting the responsebody, it is automatically converted to http response.
@Controller: This annotation is just a specialized version of @Component and it allows the controller classes to be auto-detected based on classpath scanning.
@RestController: This annotation is a specialized version of @Controller which adds @Controller and @ResponseBody annotation automatically so we do not have to add @ResponseBody to our mapping methods.
The @Controller annotation indicates that the class is a "Controller" like a web controller while @RestController annotation indicates that the class is a controller where @RequestMapping methods assume @ResponseBody semantics by default i.e. servicing REST API
@Controller
is used in legacy systems which use JSPs. it can return views. @RestController
is to mark the controller is providing REST services with JSON response type. so it wraps @Controller
and @ResponseBody
annotations together.
@RestController
is composition of @Controller
and @ResponseBody
, if we are not using the @ResponseBody
in Method signature then we need to use the @Restcontroller
.
Instead of using @Controller and @ResponseBody, @RestController let's you expose Rest APIs in Spring 4.0 and above.
Success story sharing
Thymeleaf
it will not work with@RestController
because of@ResponseBody
which included in this annotation.@ResponseBody
makes the returned objects to something that could be in the body, e.g. JSON or XML (source)