I'm wondering is it possible to have path variable in server.servlet-path with DispatcherServlet? I know of course it possible in controller, but I'd like to have it in one place instead of updating 70 endpoints.
Like:
server.servlet-path=/{client-name}/api/v4
And for example that client-name will be available in request attributes, headers, etc.
Or I need to implement my own dispatcher which will do that logic?
Related
I am designing a REST controller layer with the concept of different versioning which might happen in the future.
I am thinking of having separate classes with version number as follows.
#RequestMapping("/v1/api")
#RestController
class V1RestController {
}
#RequestMapping("/v2/api")
#RestController
class V2RestController {
}
Or V2RestController might extend V1RestController depending on the requirements. This is just a draft idea. But my question is if there is any Spring MVC api which can catch the URL and look up the version '/v1/api or /v2/api' and delegate the request to the right controller.
Based on my research, the best way is to make it backward-compatible, but i am sure that the reality is different and there would be some cases to have different implementations.
I know that there are other ways to design the rest controller layer for different versioning, but for now, i would like to take this approach.
Any help would be appreciated.
But my question is if there is any Spring MVC api which can catch the URL and look up the version '/v1/api or /v2/api' and delegate the request to the right controller.
DispatcherServlet intercepts the request (what to intercept it looks in "web.xml" ), and then DispatcherServlet looks at the request URL and looks for the controller whose "value" parameter (the "#RequestMapping" annotation) matches the request URL, if a match is found: control is transferred in the corresponding controller. Something like this.
I'm using spring-boot-starter-data-rest and spring-boot-starter-web.
I've made a simple project using a CrudRepository, letting spring boot generate the rest request mappings.
Now, I want to add a client -- making the rest calls -- live under ./.
Hence, I'm trying to prefix the paths for the rest calls (and only those!) with /api.
I've tried the answers from :
How to specify prefix for all controllers in Spring Boot?
using settings in the application.properties file
server.contextPath=/api/*
spring.data.rest.basePath=/api/*.
But still the static content (e.g. index.html, *.js, *.css) is not fetched using ./. There urls are also prefixed by "/api/".
The rest calls are properly served under /api/foos.
Is there a way to tell spring not to treat urls that lead to sources located in src/main/resources/public as 'rest-controllers'?
Update
Setting the property
spring.data.rest.basePath=/api/*
works perfectly. (I still had a programmatic bean configuration in my sandbox overriding this setting).
Spring controllers are made for serving both HTML and JSON/XML. The first one is done via Spring MVC Views and some template engine like Thymeleaf, the latter is handled entirely by Spring and #RestController.
There's no way to have a context path for only the controllers that returns JSON or XML data, and not for the other controllers as well, this also goes for static content. What you typically do is have some static variable containing the prefix you want for your APIs, and the use that in the controller's #RequestMapping. i.e.
#RestController
#RequestMapping(MyConstants.API_LATEST + "/bookings")
public class MyBookingsController {
...
}
You probably want to approach the prefix problem with something along these lines anyway. It is common to have to support older API versions when you have breaking changes, at least for some time.
I'm migrating a Play! 1.2 web application and moving to Spring Boot + Spring MVC. Some views contain URLs to other endpoints. For example, I display the book title on the page and next to it I want to add the URL to go the book's details page (e.g. localhost/books/{id}).
In Play! 1.2 the controllers are static, and there is also a Router which can create the full URL for a method belonging to another controller (Router.getFullUrl("BookController.bookDetails", args)), but how do I achieve this with Spring MVC?
Best regards,
Cristian.
If you are trying to get the app/deployed name automatically in .jsp files to make the urls, then please make use of context path. An example below :
<c:set var="context" value="${pageContext.request.contextPath}" />
<script src="${context}/themes/js/jquery.js"></script>
From your requirement "admin.myapp.com","admin-test.myapp.com" are server names right? Something like http://admin.myapp.com/book/{bookId},http://admin-test.myapp.com/book/{bookId}. In Spring app, relative path in jsp can be accessed using pageContext.request.contextPath
I also found the UriComponentsBuilder and ServletUriComponentsBuilder. They are similar to the Play! Framework router and provide methods for building URI's, handling parameters and the query etc. We chose to annotate the controllers' methods using constants and then use the same constants with the UriComponentsBuilder to build back the path and create the request query for GET requests.
I want to use Spring MVC 3.0 to build interfaces for AJAX transactions. I want the results to be returned as JSON, but I don't necessarily want the web pages to be built with JSP. I only want requests to the controllers to be intercepted/routed through the DispatcherServlet and the rest of the project to continue to function like a regular Java webapp without Spring integration.
My thought was to define the servlet-mapping url pattern in web.xml as being something like "/controller/*", then have the class level #RequestMapping in my controller to be something like #RequestMapping("/controller/colors"), and finally at the method level, have #RequestMapping(value = "/controller/colors/{name}", method = RequestMethod.GET).
Only problem is, I'm not sure if I need to keep adding "/controller" in all of the RequestMappings and no matter what combo I try, I keep getting 404 requested resource not available errors.
The ultimate goal here is for me to be able to type in a web browser "http://localhost:8080/myproject/controller/colors/red" and get back the RGB value as a JSON string.
You are not correct about needing to add the entire path everywhere, the paths are cumulative-
If you have a servlet mapping of /controller/* for the Spring's DispatcherServlet, then any call to /controller/* will be handled now by the DispatcherServlet, you just have to take care of rest of the path info in your #RequestMapping, so your controller can be
#Controller
#RequestMapping("/colors")
public class MyController{
#RequestMapping("/{name}
public String myMappedMethod(#PathVariable("name") String name, ..){
}
}
So now, this method will be handled by the call to /controller/colors/blue etc.
I don't necessarily want the web pages to be built with JSP
Spring MVC offers many view template integration options, from passthrough to raw html to rich templating engines like Velocity and Freemarker. Perhaps one of those options will fit what you're looking for.
What's the difference, really, between filters and interceptors? I realize that interceptors fire before and after an action, recursively, and filters can be configured to fire on actions and on certain url patterns. But how do you know when to use each one?
In the book I'm reading on Struts 2, it seems that interceptors are being pushed and I even followed a tutorial to write an Authentication Interceptor to make sure a user is logged in. However, if the user tries to access a URL that doesn't have an action associated with it, the interceptor doesn't catch it, which means I'd have to associate an action with every jsp that I want to be secure. That doesn't seem right.
I can make an Authentication Filter that handles URLs so that I don't have to do that, but then, what's the point of interceptors?
The most significant difference is that "interceptors" are a part of the Struts 2 framework, and are only part of the request handling that is done by the Struts 2 framework. "Filters" on the other hand are a part of the Servlet Specifcation; in other words, they are part of the Servlet API. If you are using Struts 2, you should use interceptors for wrapping functionality around your Struts 2 actions. If you are trying to wrap functionality around requests coming to your webapp, but not being handled by Struts 2, then a filter might be more appropriate.
BTW, the entire Struts 2 Framework is deployed inside a filter configured in your web app, declared in your webapp's deployment descriptor ( web.xml ) like:
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
This filter, which is configured to catch all requests URL patterns, is the entry point into the entire Struts 2 framework.
I hope that helps.
the interceptor stack fires on every request.
filters only apply to the urls for which they are defined.
edit -- you use one or the other depending on need. Lets say you need to verify a cookie is present for every request. User an interceptor. Lets say that you need to pop up an external app on some requests (driven by a url), use a filter.
I think interceptors are the more commonly used tool...
why would you have a url with no associated action?
What is Interceptor ?
The Struts 2 Framework uses the concept of Interceptors to share the solution for some common concerns by different actions.
As we know the framework invokes a particular Action object on the submssion of a request for it. But before executing of Action, the invocation is intercepted by some other object to provide additional processing required.
Similarly after the execution of Action, the invocation can be intercepted again. This intercepting object is known as Interceptor.
So the purpose of using Interceptor is to allow greater control over controller layer and separate some common logic that applies to multiple actions.
Struts 2 framework has already provided its own set of Interceptors which can be used in the application to provide required processing before and after the Action classs execution.
One of those is "Alias Interceptor" that I am going to discuss here.
Alias Interceptor:
Alias Interceptor is used in case of Action chaining. Action chaining means one Action calls other Action after successful execution of first action.
This interceptor aliases a named parameter to a different parameter name. In action chaining, when two different action classes share a common parameter with a different name, this Interceptor is used to give an alias name to a parmeter of first action class, which matches the parameter name in the second action class.
The alias expression of action should be in the form of :
#{ 'name1' : 'alias1' , 'name2' : 'alias2' }
As per the struts 2 life cycle/architecture no interceptors are executed before filter. So if there is no action mapping for your request then it's failing in while passing through filter.
As a rule of thumb
Filters are run before each request. The struts itself is a filter.
interceptors can run before, after struts actions. They will not run if the request does not end with .action.
So, some example of filters could be:
If you want to compress your js and css files, you should go for filters not interceptors.
If you want only certain IP address access your web site you must develop it as filter and check request ip address.
If you want to safe your site against CSRF attack you must write a filter to check CSRF token on requests.
If you want to log your site response per request time, you can use a filter to calculate the time before and after chain.doFilter(request, response)
Theoretically you can develop an struts web application without developing your own interceptors and using filtersonly. But you will face lots problem and code boiler filters.
Lots of struts 2 features are build with interceptors, you can find it in struts-default.xml (https://struts.apache.org/docs/struts-defaultxml.html) the list will help to find when interceptors can be used. (For example ParametersInterceptor runs before actions to apply submited form values to actions)
While working with interceptors you can easily access struts features, for example getText from message resources, get current action name and name space, change the action flow.
Considering above here are some cases which can be developed by interceptors:
If you want that only logged in users can access certain actions, you must develop it with interceptors.
If you want to keep track which actions user is navigation. You can use an interceptor to keep track of visited actions.
If you want to handle your action errors in a single point, you can use an interceptor which catch all invocation.invoke()
The interceptors are providing the filter and Chain of Responsibility design pattern for struts actions, while filters provide this pattern to your whole web application.
Struts 2 Framework is not dependent on Servlet API.
Struts 2 Actions are not coupled to a container. Most often the servlet contexts are represented as simple Maps, allowing Actions to be tested in isolation.
Filter is a part of Servlet API so Struts 2 Framework uses the concept of Interceptors to share the solution for some common concerns by different actions.
Also you can easily write test cases for Interceptor and Action class.