My Project structure is as follows
|src
|--main
|---webapp
|----static
|-----CSS
|-----HTML
|-----js
I am trying to return an HTML resource via my controller for links that are directly under root there is no issue but for other links, I am facing problems.
Here is my controller
#Controller
public class HtmlServer {
#RequestMapping({"/", "/index", "/index.html", "/index.jsp", "/home","/home.html","/home.jsp"})
public ModelAndView index() {
return new ModelAndView("html/index.html");
}
#RequestMapping(method = RequestMethod.GET, value = "/support/{id}/{accessToken}")
public ModelAndView start(#PathVariable Long id, #PathVariable String accessToken) {
return new ModelAndView("html/index.html");
}
}
Here is my WebMvcConfigurerAdapter extending class
#Component
#ConfigurationProperties
#Configuration
#EnableWebMvc
public class ApplicationConfig extends WebMvcConfigurerAdapter {
#Bean
public InternalResourceViewResolver internalResourceViewResolver(){
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("static/");
return internalResourceViewResolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**").addResourceLocations("static/js/")
.setCachePeriod(0);
registry.addResourceHandler("/css/**").addResourceLocations("static/css/")
.setCachePeriod(0);
registry.addResourceHandler("/support/**").addResourceLocations("/static/")
.setCachePeriod(0);
}
}
When I open / or /index.html the controller returns the given value and in return i am served the correct resource.
But when I try to use /support/1/xsdda I am mapped to /support/1/static/html/index.html Can someone explain the internals and logically point out my mistake.
Thanks!
Create folder WEB-INF inside webapp and put your HTML folder inside it
set prefix of resolver to /WEB-INF/HTML/
set suffix of resolver to .html
call it by returning "index"
The Servlet 2.4 specification says this about WEB-INF (page 70):
A special directory exists within the application hierarchy named
WEB-INF. This directory contains all things related to the
application that aren’t in the document root of the application. The
WEB-INF node is not part of the public document tree of the
application. No file contained in the WEB-INF directory may be served
directly to a client by the container. However, the contents of the
WEB-INF directory are visible to servlet code using the getResource
and getResourceAsStream method calls on the ServletContext, and may
be exposed using the RequestDispatcher calls.
Related
I'm really new to spring and that's why it can be very stupid question, but I got troubled with serving static files. I'm creating a REST api for library app and have some logic when user tries to add a book:
I get principal user from SecurityContextHolder.
I add book and add book to user's list of books
I read the bytes from base64 encoded string and write it to pdf file, stored in /resources/static
And that works. But I don't know how to get this file. I tried to do next:
I made ResourceConfig class that extends WebMvcConfigurer, but it's not worked:
#Configuration
public class ResourceConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/static/**")
.addResourceLocations(StaticAbsolutePath.getPath());
}
}
Oh, the StaticAbsolutePath.getPath() is the metod I made to get path to static directory:
public class StaticAbsolutePath {
private static final String path = "A:\\java\\projects\\books\\src\\main\\resources\\static";
public StaticAbsolutePath() {
}
public static String getPath() {
return path;
}
}
I decided that my security config is blocking this path cuz I'm not authorized, so I added this to config class:
http.authorizeRequests().antMatchers("/static/**").permitAll();
But it'a also was useless. When I try to serf to http://localhost:8080/static/1252356147.pdf, it says that "Whitelabel Error Page".
And here is the screen of resources directory:
So if you know what can be the problem, please tell me, I'd really apreciate it!
Here is the full code of SecurityConfig:
#Configuration #EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
private final BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
CustomAuthenticationFilter customAuthenticationFilter = new CustomAuthenticationFilter(authenticationManagerBean());
customAuthenticationFilter.setFilterProcessesUrl("/api/login");
http.csrf().disable();
http.authorizeRequests().antMatchers("/api/login/**").permitAll();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().antMatchers(HttpMethod.POST, "/api/users/").authenticated();
http.authorizeRequests().antMatchers(HttpMethod.GET, "/api/user/current").authenticated();
http.authorizeRequests().antMatchers(HttpMethod.POST, "/api/books/**").authenticated();
http.authorizeRequests().antMatchers(HttpMethod.GET, "/api/books/**").permitAll();
http.authorizeRequests().antMatchers(HttpMethod.PUT, "/api/books/**").authenticated();
http.authorizeRequests().antMatchers("/static/**").permitAll();
http.addFilter(customAuthenticationFilter);
http.addFilterBefore(new CustomAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
UPDATE
I understood that in resources/staic directory should be stored files like HTML and CSS thanks to #Akhil. And I also added the lines of code that he suggested. So my ResourceConfig class now looks like this:
private static final String[] CLASS_PATH_RESOURCE_LOCATIONS = {
"A:\\downloads\\"
};
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/pdf/**")
.addResourceLocations(CLASS_PATH_RESOURCE_LOCATIONS)
.setCacheControl(CacheControl.noCache().cachePrivate())
.resourceChain(true)
.addResolver(new PathResourceResolver());
}
And I changed the directory to store user uploaded files:
But it still not working :(
Full project structure:
Firstly, static files mean files that rarely change for example HTML, CSS files, etc. In your case, the user can upload a pdf file anytime that indicates it's not a static file. What I would suggest is to use a different directory to store PDF and give that path in your resourceConfig. However, if you want to store it in your /resources/static directory then you can do something like this.
ResourceConfigs:
#Configuration
#EnableWebMvc
public class ResourceConfigs implements WebMvcConfigurer {
private static final String[] CLASS_PATH_RESOURCE_LOCATIONS = {
"A:\\downloads\\pdfFiles\\"
};
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pdf/**")
.addResourceLocations(CLASS_PATH_RESOURCE_LOCATIONS)
.setCacheControl(CacheControl.noCache().cachePrivate())
.resourceChain(true)
.addResolver(new PathResourceResolver());
}
}
With this configuration, you can have links like this,
http://localhost:8080/pdf/**
You don't need to configure spring security for this
I am trying to develop a simple Spring MVC with no XML application .its basically show a simple home page. I am using tomcat on JetBrains IDE for development and problem is that when I run it on tomcat I see 404 error this is url http://localhost:8080/MySpringSecurityApp_war/
this is a controller
#Component
public class DemoController {
#GetMapping("/")
public String showHome(){
return "home";
}
}
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.luv2code.springsecurity.demo")
public class DemoAppConfig {
//define a bean for view resolver
#Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver viewResolver=new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
public class MySpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] {DemoAppConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
this is error log
9-Jun-2020 13:32:07.511 WARNING [http-nio-8080-exec-1] org.springframework.web.servlet.PageNotFound.noHandlerFound No mapping found for HTTP request with URI [/MySpringSecurityApp_war/] in DispatcherServlet with name 'dispatcher'
09-Jun-2020 13:32:07.604 WARNING [http-nio-8080-exec-4] org.springframework.web.servlet.PageNotFound.noHandlerFound No mapping found for HTTP request with URI [/MySpringSecurityApp_war/] in DispatcherServlet with name 'dispatcher'
this is also how my project structure
You need to define a resource path if you adding something into your URL (after host part basically in your case MySpringSecurityApp_war) you are calling localhost:8080/MySpringSecurityApp_war/ but you didn't define the resource path anywhere so I guess what you need to do is either add #RequestMapping("/MySpringSecurityApp_war/") at class level or just call localhost:8080/ without any resource path
You can also use #RestController in place of #Component.
I hope it will work.
I know this question has a lot of answers but i cannot solve mine so that is why i decided to put up the question
I want to resolve both jsp and html files. Below is my spring resolver configuration
#Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix("");
return resolver;
}
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/WEB-INF/views/static");
}
and controller class is below:
#RequestMapping("/testApi2")
#Controller
public class TestController2
{
#RequestMapping("/showHomePage")
public ModelAndView showHome(){
return new ModelAndView("/static/about.html");
}
}
I have also attached screen shot of my directory structure, it is giving 404 on every request
I think that you should add to your web resolver config class one very special handling configurer:
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
This method enables static resources processing.
After some efforts , thanks to lot of documentation on Spring , i was able to resolve the issue
I found a solution(searched on net) with which we can use both JSP and HTML as views
Forget the question , below are the new settings
Static resources (.css,.js,.jpg) are placed in webapp/assets/
HTML files are in /WEB-INF/static/
Here is my configuration file :
#Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix("");
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**") //
.addResourceLocations("/assets/").setCachePeriod(31556926);
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
Please note i have used resolver.setSuffix("") both HTML and JSP
HTML code :
<link rel="stylesheet" href="/taxi/assets/css/theme-pink.css" />
Here taxi is the context root , means name of the project
Now if i run the below URL , it will fetch the image or CSS of js
localhost:8080/taxi/assets/css/icons.css
I'm trying to make use of Sitemesh (3) templating with Spring Boot (4+) using Java annotation based config.
When I hit the controller URL, the handler method is invoked.
The Sitemesh filter is activated (debugging proves that).
However I am getting a 404, which I believe is because with the config I have the Freemarker template isn't found (wrong path somewhere).
Code follows, any suggestions what I'm doing wrong would be great!
Filter:
#WebFilter
public class SitemeshFilter extends ConfigurableSiteMeshFilter {
#Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
System.out.println("in sitemesh filter");
builder.addDecoratorPath("/*", "templates/main.ftl")
.setMimeTypes("text/html")
.addExcludedPath("/javadoc/*")
.addExcludedPath("/brochures/*");
}
Controller:
#Controller
public class UserController {
#Autowired
MemberService memberService;
#RequestMapping(value="member/{id}")
public ModelAndView viewMember(#PathVariable("id") int memberId, ModelAndView mv) {
mv.setViewName("member");
ClubMember member = memberService.getClubMember(memberId);
mv.addObject("member", member);
return mv;
}
}
Main class:
#SpringBootApplication
#ServletComponentScan
#EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})
public class ClubManagementApplication {
public static void main(String[] args) {
SpringApplication.run(ClubManagementApplication.class, args);
}
}
Application.properties:
spring.mvc.view.prefix=/views/
My templates live in :
src/main/resources/templates <- this is where I've put the sitemesh templates live
src/main/resources/views <- here are the Freemarker pages
In case anyone else has same issue:
templates ended up in resources/templates
sitemeshfilter:
#Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
builder.addDecoratorPath("/*", "/main.ftl")
.setMimeTypes("text/html", "application/xhtml+xml", "application/vnd.wap.xhtml+xml");
}
Note nothing before '/main.ftl'
I'm struggling with trying to return a static web page from a spring MVC controller.
I followed this tutorial: http://www.tutorialspoint.com/spring/spring_static_pages_example.htm and yet it still isn't working.
This is how I defined the configuration (used configuration class):
#Configuration
#EnableWebMvc
#EnableTransactionManagement
#ComponentScan({ "com.my.web.api"})
#ImportResource("classpath:db-context.xml")
public class ApiServletConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/resources/");
internalResourceViewResolver.setSuffix("*.html");
return internalResourceViewResolver;
}
}
The controller method:
#RequestMapping(value = "/{id}/view", method = RequestMethod.GET, produces = "text/html")
#ResponseBody
public String getPostByIdHtml( #PathVariable String id) throws IOException {
return "/resources/Post.html";
}
Under the webapp folder there's a folder named "resources" and under which there's a file "Post.html". What else should I do in order to get this page returned as HTML instead of getting the string "resources/Post.html"?
Thanks for the help.
Please remove the annotation #ResponseBody. Your browser should be redirected to the desired page once the annotation is removed.
This annotation indicates that the value returned by a method in your controller should be bound to the web response body. In your case, you do not need that: you need Spring to render page /resources/Post.html, so no need for this annotation.