I saw a lot people has similar problem but no answer works for me. What I'm doing is trying to embed Jetty with Spring 4 with zero configuration. I put some of my code below for better describe my question:
JettyStarter.class
public class JettyStarter {
...
private static final String CONFIG_LOCATION = "com....config";
private static final String DEFAULT_MAPPING_URL = "/*";
private static final String DEFAULT_CONTEXT_PATH = "/";
...
private ServletContextHandler getServletContextHandler() throws IOException {
WebApplicationContext context = getContext();
ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
contextHandler.setErrorHandler(null);
DispatcherServlet dispatcherServlet = new DispatcherServlet(context);
ServletHolder servletHolder = new ServletHolder("Servlet Dispatcher", dispatcherServlet);
servletHolder.setInitOrder(1);
contextHandler.addServlet(servletHolder, DEFAULT_MAPPING_URL);
contextHandler.addEventListener(new ContextLoaderListener(context));
contextHandler.setResourceBase(new ClassPathResource("webapp").getURI().toString());
contextHandler.setContextPath(DEFAULT_CONTEXT_PATH);
return contextHandler;
}
private void startJetty() throws Exception
{
...
HandlerCollection handlers = new HandlerCollection();
handlers.addHandler(getServletContextHandler());
...
server.setHandler(handlers);
server.start();
server.join();
}
private WebApplicationContext getContext() throws IOException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation(CONFIG_LOCATION);
...
return context;
}
...
}
WebMvcConfig.class
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com...controllers")
public class WebMvcConfig extends WebMvcConfigurerAdapter{
...
@Bean
public InternalResourceViewResolver getInternalResourceViewResolver()
{
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/jsp/view");
internalResourceViewResolver.setSuffix(".jsp");
internalResourceViewResolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
return internalResourceViewResolver;
}
}
HomeController.class
@Controller
public class HomeController {
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(@RequestParam(value="error", required=false) boolean error, ModelMap model)
{
...
return "/pub/login";
}
}
Finally, after the server started, I got 404 error with the following message while trying to access localhost:8080/login
WARNING: No mapping found for HTTP request with URI [/WEB-INF/jsp/view/pub/login.jsp] in DispatcherServlet with name 'Servlet Dispatcher'
I'm pretty sure resource "login.jsp" is under the folder "/webapp/WEB-INF/jsp/view/pub" within the package. But why it keeping saying it can not be found?!
Solution:
Weird restriction that I cannot answer myself question within 8 hours.
By traced in Spring's source code, I eventually got my page display. The reason is I set Jetty ServletContextHandler's ResourceBase as "webapp", and created "WEB-INF" sub folder under it, all resources under "WEB-INF/jsp/view/..." as well. But the folder WEB-INF is unseeable by ResourceHttpRequestHandler as we can see the code there:
protected boolean isInvalidPath(String path) {
return (path.contains("WEB-INF") || path.contains("META-INF") || StringUtils.cleanPath(path).startsWith(".."));
}
So, the solution is change the resource base to "webapp/WEB-INF", and change InternalResourceViewResolver prefix to "/jsp/view" as well. It does work though!
Now my question is, ResourceHttpRequestHandler is known by to be used to restrict directly resource access, a servlet should not use it, why my none-config version load it in? but not for XML-config version? is XML-config using any other handler by pass this restriction or something I'm missing? Appreciate for anybody to forward.