Spring RequestMapping with root path (/{custom}) - spring

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

Related

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);
}
};
}
}
}

Why is my browser downloading file instead of rendering SpringBoot & Sitemesh output?

I'm trying to use SpringBoot with Freemarker and Sitemesh.
When I go to a URL at the moment the request is handled by the application, data loaded and HTML output generated, but for some reason the browser has decided it wants to download the file (which contains the correct content) rather than rendering it as a page.
This was working a while back, trouble is I'm not sure which change I've made has broken it!
Sitemesh filter:
#WebFilter
public class SitemeshFilter extends ConfigurableSiteMeshFilter {
private static final Logger LOG = Logger.getLogger(SitemeshFilter.class);
#Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
LOG.debug("SiteMeshFilter creation");
builder.addDecoratorPath("/*", "/templates/main.ftl")
.addExcludedPath("/h2console/*");
}
}
Application:
#ServletComponentScan
#SpringBootApplication
#EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})
public class ClubManagementApplication {
private static Logger LOG = Logger.getLogger(ClubManagementApplication.class);
public static void main(String[] args) {
SpringApplication.run(ClubManagementApplication.class, args);
}
}
Snippet of controller:
#Controller
public class ClubController {
#Autowired
ClubService clubService;
#RequestMapping(value = {"Club/{id}","club/{id}"})
public ModelAndView viewClub(#PathVariable("id") int clubId) {
ModelAndView mv = new ModelAndView("club");
....
return mv;
}
}
EDIT:
From the HttpServletRequest object in controller...
accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
In the response headers:
Content-Type : application/octet-stream;charset=UTF-8
I guess the content type is the problem....just gotta find why it's being set like that.
In case someone else stumbles on this question, I changed my template file from an ftl to a html extension and suddenly it has woken up.
#Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
LOG.debug("SiteMeshFilter creation");
//builder.addDecoratorPath("/*", "/templates/main.ftl");
builder.addDecoratorPath("/*", "/templates/main.html");
}

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 MVC TrailingSlash matching

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?

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