Can we have multiple controllers in a Spring MVC application? If yes, can someone provide a working example to support this concept?
Of course you can. There's not much to provide:
#RestController
public class UserController {
#GetMapping("/users")
// method etc.
}
#RestController
public class AccountController{
#GetMapping("/accounts")
// method etc.
}
Related
I have a Spring Boot App with several WebAPIs. How can I configure the path prefix of each WebAPI differently via application properties?
For example I have a UserRestController and a StarShipRestController. Both are part of different WebAPIs, but served by the same Spring Boot App. The RestControllers should only feature the last part of the URL to the resource. The path prefix should not be part of the RestController:
#RestController
#RequestMapping("users")
class UserRestController {
// methods...
}
and
#RestController
#RequestMapping("starships")
class StarShipRestController {
// methods...
}
The concrete path prefixes are in application.properties:
api.user.pathPrefix=/api/v1
api.starship.pathPrefix=/universe
The question is how to apply the path prefixes to the RestControllers?
If there was only one WebAPI in the Spring Boot App, I could use a WebMvcConfigurer. But that doesn't work because I have several WebAPIs.
#Configuration
public class WebMvcConfig implements WebMvcConfigurer {
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix("api", HandlerTypePredicate.forAnnotation(RestController.class));
}
}
You can only have one context-path for a single Spring-Boot application (which can be configured using server.servlet.context-path). This means what you are asking is not possible.
The only way to achieve it is by changing the #RequestMapping annotations in your Controllers to include the full path that you want.
#RestController
#RequestMapping("/api/v1/users")
class UserRestController {
// methods...
}
#RestController
#RequestMapping("/universe/starships")
class StarShipRestController {
// methods...
}
To my knowledge, there is no other way.
Considering your request, I ask myself if you shouldn't have two different Spring-Boot applications instead of just one.
#PostMapping("/api/file/delete")
public String deleteMultipartFile(HttpServletRequest request) {
try {
String keyname=request.getParameter("keyname");
s3Services.deleteFile(keyname);
return "redirect:/welcome";
} catch(Exception e) {
return "redirect:/welcome";
}
}
Actual result :
printing "redirect:/welcome " in white page
Expected Result : it redirect to welcome modal.
Spring is a Java application framework and Spring boot is an evloution of Spring that helps create stand-alone, production-grade spring based application that you can "just run".
Spring boot supports #Controller and #RestController annotation, where
#Controller annotation indicates that the annotated class is a controller. It is a specialization of #Component and is autodetected through classpath scanning. It is typically used in combination with annotated handler methods based on the #RequestMapping annotation. #RestController is a sibling convenience annotation for creating Restful controllers.
If you created spring boot application having controller with annotation #Controller and you have #GetMapping method which return index.html(file location /src/main/resources/templates/index.html) view page. like code below :-
#Controller
public class MyController{
#GetMapping("/")
public String indexPage(){
return "index";
}
#GetMapping("/index")
public String routeWithIndex(){
return "redirect:/";
}
}
Both function returns index.html page. If you want more knowledge about spring annotation of #Controller and #RestController with examples visit baeldung site or official site about spring.
I created a front end controller within a project containing multiple (REST) applications. The issue is now that, the controller gets applied for all applications I try to access through the browser. I would like to ask whether the is a configuration or annotation to define for which application the controller should get applied.
This is the code of the controller:
#Controller
public class FrontendController {
#RequestMapping(value = "/")
public String index() {
return "index";
}
}
In the same package the application which serves the front end sources is implemented:
#SpringBootApplication
public class WebServer {
public static void main(String[] args) {
// Tell server to look for web-server.properties or web-server.yml
System.setProperty("spring.config.name", "web-server");
SpringApplication.run(com.studienarbeit.chaoscenter.services.departments.DepartmentsServer.class, args);
}
}
The other applications are in different packages and yet they still serve the front end sources. There are no other controllers in the project and the other applications use Spring Data REST repositories.
Note: Each application runs on its own port.
Note 2: I tried the approach using a profile for the controller:
#Profile("web-server")
Since I work with IntelliJ, I set the active profile to web-server and add the following flag in the VM Options for the specific application:
-Dspring.profiles.active=web-server
Somehow still my other applications access the front end controller. Maybe I did miss something?
Note 3: The other application implementations look basically exactly like the WebServer application and they use Spring Data REST repositories which look like this:
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
}
Use specific RequestMapping values for each of your controller classes like :
#Controller
#RequestMapping("/controller1")
public class FrontendController {
#RequestMapping(value = "/")
public String index() {
return "index";
}
}
So you would consume this endpoint with the url http://localhost:8080/controller1
Also, if you're not going to use Mvc Views and this will be only a Rest Controller, use #RestController insted #Controller.
#RestController
#RequestMapping("/controller1")
public class FrontendController
It's a combination of #Controller and #ResponseBody annotations. Detailed information could be found at here.
I have written some RESTful webservices using Spring Framework (by reading posts online / video tutorials etc.) , however I still have some doubts.
When we write a web-application using Spring MVC module we use controller code, similar to below:
#Controller
public class SimpleController {
#RequestMapping("/welcome")
ModelAndView handleIncomingWelcomeReq() {
ModelAndView mw = new ModelAndView("WelcomePage","welcomeKey","WelcomeKey's value!");
return mw;
}
}
In the above code there is ModelAndView object which this controller returns, and this can be invoked like this URL:
http://localhost:8080/contextRoot/welcome
Now, if we exclude the "view" part and return just the model doesn't it act like a web service?
So my doubt is, in Spring do we used the same API/jar's to create web-application or RESTful web services?
The things which I read is that for Spring REST support, it has annotation #RestController annotation (which itself is like #Contoller + #ResponseBody annotations).
So what is the difference in which the implementation of REST WS and web-applications differs in Spring Framework?
Can anyone help me understand this?
Yes we can write RestService & web application using Spring. Use #RestController to expose a REST service and #Controller for web application.
#RestController is a meta-annotation with #Controller and #ResponseBody. #Controller will search through the registered ViewResolvers, whereas #RestController will not.
#Controller
public class SimpleController {
#RequestMapping("/welcome", method = RequestMethod.GET, produces="application/json")
public #ResponseBody JSONObject handleIncomingWelcomeReq() {
JSONObject j = new JSONObject();
j.put("welcomeKey", "WelcocmeKey's value!");
return j;
}
Here is the code which returns response in json mostly user id Rest Apis.
I would suggest to use #Controller instead of #RestController, as #RestController, won't scan your views. So, in case if your application has it's own views and also needs to expose it's services, you can use #Controller along with the #ResponseBody annotations, with output as JSON.
Another option is to have completely different URL for RESTful webservices, where a different controller will handle the request. These different controllers can be annotated with #RestController.
Pseudo-code:
class SomeController {
def myAction() {
// controler is an property passed via ctor
controller.redirect(toWhereever)
}
}
// another variant
class AnotherController {
def myAction(controller) {
// controler is an method argument
controller.redirect(toWhereever)
}
}
Any suggestions?
Edit: Because the question is a bit dry you could try to spice up your answers with some experience with the framework and what do you think is better with that approach.
Spring MVC and Grails (built ontop of spring) favour dependency injection with no inheritance whatsoever. Each controller is a class that does not extend anything. Instead you can inject other components into it (using dependency-injection). For example:
#Controller
#RequestMapping("/user")
public class UserController {
#Inject
private UserService service;
#RequestMapping("/register")
public String register(User user) {..}
}
#Controller
#RequestMapping("/orders")
public class OrderController {
#Inject
private UserController userController
}
(Although it is not a common practice to inject controllers into other controllers, you can inject any object)
web2py - controllers are functions
web.py
puremvc - controllers are Commands
camping - odd, replaces internal controllers
limonade - procedural
Django has decided to use different terms for the MVC pattern. In django-speak "view" is what most people call controller. a django view is just a function taking a request instance and returning a response instance. Roughly it looks like this:
from django.http import HttpResponse, Http404
import datetime
def current_datetime(request):
if request.method != 'GET':
raise Http404
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
JSF & Spring MVC
An easy tutorial for JSF: www.coreservlets.com/JSF-Tutorial/jsf2/index.html#Annotations
A basic example from SpringSource: http://src.springframework.org/svn/spring-samples/mvc-basic/trunk
Q: Why JSF
A:
You can perform your action at SimpleController#doSomething
#ManagedBean
public class SimpleController {
public String doSomething() {
...
}
}
And SimpleController does not extend any controller, #ManagedBean helps to make it look like a controller.
Q: Why Spring MVC
A:
You can perform your action at "..../doSomething"
#Controller
public class SimpleController {
#RequestMapping("/doSomething")
public String doSomething() {
...
}
}
SimpleController does not extend any controller.
#Controller helps to make the class a controller
#RequestMapping bind its url to "/doSomething"
[sorry for bold url, i can only post maximum one url in an answer as a newbie :-S]
Struts 2 also lets you do this. All the actions are simple java beans.