Spring MVC TrailingSlash matching - spring

I am using Spring MVC 4.1, and this is the core config:
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = {""})
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(true);
configurer.setUseTrailingSlashMatch(false);
}
....
}
#Controller
#RequestMapping("/api/deps")
public class DepartmentCtrl {
#RequestMapping(value = "", method = RequestMethod.GET)
public Result index() {
return ...;
}
}
While when I open this the url:
/context/api/deps
I will get the result as expected, however once I will get a 404 once I visit the link:
/context/api/deps/
As shown, I have config the PathMatchConfigurer by setUseTrailingSlashMatch(false) , but it seems that it does not work.
Is there anything wrong in my configuration?

use this:
setUseTrailingSlashMatch(true)
According to javadoc, setUseTrailingSlashMatch determines:
Whether to match to URLs irrespective of the presence of a trailing
slash. If enabled a method mapped to "/users" also matches to
"/users/".
Honestly, there is no need for this piece of configuration, since its enabled by default and you by passing false to it, disabled it.

What happens when you pass "/" in the value attribute of RequestMapping Annotation?

Related

AutoConfigure RestController Spring Boot

I have tried to find documentation on how to manually configure a RestController (i.e in a Configuation class). That means without using the RestController annotation. Considering all the other annotations, like mapping, pathvariables etc. is at all possible?
A controller is essentially a component with a request mapping. See RequestMappingHandlerMapping.
#Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
If you want to instantiate a "rest controller" through configuration, you can probably do so via the following:
#Configuration
public class MyConfiguration {
#Bean
public MyController() {
return new MyController();
}
}
#ResponseBody
public class MyController {
#RequestMapping("/test")
public String someEndpoint() {
return "some payload";
}
}
But I don't think you'll be able to configure the request mappings (path variables, etc) in the configuration though; at least I haven't seen an example nor figured out how.

How to get a respose from a localhost url exactly http://localhost:8888/

I have two projects setting up Springboot in it, now, I am going to run these two springboot on eclipse, I set up the port 8888 for projectB.
Here is my projectB controller with RequestMapping.
#RequestMapping(value = "test", method = RequestMethod.GET)
public #ResponseBody String test() {
return "testtesttest";
}
I need to call a url from jquery method that url is to read the respose from a controller in projectB.
how can I call this url ??
I tried "http://localhost:8888/test" and "http://127.0.0.1:8888/test"
but I did not get anything from the response.
The error shows up as :
please give me the solution for this
very appreciated.
Add below code in your application's main class. This configures your web mvc cors mapping to allow request from " * "
#SpringBootApplication
public class Application {
#Configuration
public class MyConfiguration {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
logger.info("Added CORS config");
registry.addMapping("/**").allowedOrigins("*").maxAge(3600);
}
};
}
}
}

Spring RequestMapping with root path (/{custom})

Let's say my website name is: foo.com
When a user types foo.com, I want to show index.html.
When a user types foo.com/something, I want the server catches the request at the controller.
Here is what I did in the HomeController:
#Controller
public class HomeController {
#RequestMapping(value={"/"}, method=RequestMethod.GET)
public String getHome() {
return "index.html";
}
}
And, the CustomController should catch the request
#Controller
public class CustomController {
#RequestMapping(value={"/{custom}"}, method=RequestMethod.GET)
public String getCustom(#PathVariable String custom) {
// Do something here..
}
}
However, it throws an error: Circular view path [index.html]: would dispatch back to the current handler URL [/index.html] again. It's because the CustomController catches the GET request: foo.com/index.html after the HomeController returns the string: index.html.
I did some research like this:
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/assets"); // My asset
registry.addResourceHandler("index.html").addResourceLocations("file:/index.html");
} // It's not working
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/" + FileNames.INDEX);
} // This also not working
}
And changing the annotation from #Controller to #RestController in the CustomController is not an option.
Also, I don't have JSP files in the project - they are plain *.html files.
I am using Spring 1.3.3 release, so please help me out.
This solution works with ui-router (AngularJS library). Also, you have to change $resourceProvider setting:
// In your app module config
$resourceProvider.defaults.stripTrailingSlashes = false;
Then, in the Spring server codes, you can do this:
#RequestMapping(value = "/{custom:[^\\.]*}")
public String redirect(#PathVariable String custom) {
// Do something here...
return "forward:/";
}
Found the solution at this link: https://spring.io/blog/2015/05/13/modularizing-the-client-angular-js-and-spring-security-part-vii

Spring Boot url mappings order for controllers and static pages

I have a Spring Boot web application which is meant to serve both static and controller based (ModelAndView) pages. Problem is that a controller can serve something like /{string} and a static page must be served with /test.
The problem is that the controller mapping takes precedence, and I need to avoid that. If the user hits /test, he must be forwarded to the test.html static page.
I tried to use the order property of ViewControllerRegistry in this way, with no success:
#Configuration
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/test").setViewName("forward:/test.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE); // but I tried with 0 and -1 as well: annotated controllers should have order equals to 0
}
}
This is my SpringBootApplication class:
#SpringBootApplication
public class VipApplication {
public static void main(String[] args) {
SpringApplication.run(VipApplication.class, args);
}
}
And this is the controller code:
#Controller
public class VipController {
#RequestMapping(value = "/{string}")
public ModelAndView vip(#PathVariable("string") String string) {
ModelAndView mv = new ModelAndView("mypage");
return mv;
}
}
How can I reorder the mappings to make sure static pages are considered before annotated controllers?
(I'm not sure, but) I suggest to override WebMvcConfigurerAdapter.addResourceHandlers() method and configure order of resource handler by invoking ResourceHandlerRegistry.setOrder()

Spring URI PathVariable with file extension not working

I'm having trouble working out why the file extension (.jpg) in the following request is being stripped before calling my controller method:
GET http://blah.com/assets/picture.jpg
I've set the content negotiation to not favour path extensions:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.blah" })
public class PlatformWebAppConfig extends WebMvcConfigurerAdapter {
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
configurer.favorParameter(false);
configurer.useJaf(false);
configurer.defaultContentType(MediaType.APPLICATION_JSON);
}
}
my controller is this:
#Controller
public class FileUploadRestApi {
#RequestMapping(
value = "/assets/{filename}",
method = RequestMethod.GET)
public void downloadFile(HttpServletResponse response,
#PathVariable("filename") String filename,
Principal principal) {
// ERROR: 'filename' has extension stripped !!!!
}
}
I've also tried adding the following to the PlatformWebAppConfig class above with no luck:
#Override
public void configurePathMatch(PathMatchConfigurer matcher) {
matcher.setUseSuffixPatternMatch(true);
matcher.setUseRegisteredSuffixPatternMatch(true);
}
I've tried to debug the issue and I've got as far as seeing ContentNegotiationManagerFactoryBean.afterPropertiesSet is definitely seeing the favorPathExtension setting as false and not setting up a content negotiation strategy (as expected).
Update:
If I change the request mapping to
"/assets/{filename:.+}"
the filename will include the extensions but this does not explain why setting all those configurers did not achieve anything????

Resources