Reputation: 2160
I have two pages: home.jsp, and stylechoosertable.jsp. home.jsp has a simple link going to stylechoosertable.jsp. Both are in src - main - webapp - views. Starting the app runs fine, loading home.jsp is fine. However, when I click the link, it goes to a 404 Not Found page.
Here is HomeController.java
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model) {
logger.info("Welcome home! The client locale is {}.");
return "home";
}
}
Here is CSSTableController.java
@Controller
public class CSSTableController {
private static final Logger logger = LoggerFactory.getLogger(CSSTableController.class);
private final CSSService cssService;
@Autowired
public CSSTableController(CSSService cssService) {
this.cssService = cssService;
}
@RequestMapping(value = "/stylechoosertable.jsp", method = RequestMethod.GET)
public List<StyleChooser> get() {
return cssService.getAllStyleChoosers();
}
}
servlet-context.xml
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
web.xml
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
A couple of things I've noticed:
Only local:8080/myspringmvc/ brings up the home page. local:8080/myspringmvc/home.jsp brings up the same 404 error, which I don't get.
On start, I can see it doing the Request/Handler mappings properly:
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/stylechoosertable.jsp],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.List com.css.genapp.CSSTableController.get()
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.css.genapp.HomeController.home(org.springframework.ui.Model)
I can't figure out why it doesn't "hit" my stylechoosertable.jsp. Any ideas?
Upvotes: 2
Views: 5848
Reputation: 279940
Most Servlet containers register a Servlet
implementation to handle JSPs. They would look like
<servlet>
<servlet-name>jspServlet</servlet-name>
<servlet-class>com.example.JspServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jspServlet</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
The *.jsp
is known as an extension mapping. A Servlet container knows about this Servlet
and the ones you've registered. The container doesn't know anything about your @Controller
beans. That are relevant to Spring only.
When a Servlet container receives a request, it goes through an order specified in the Servlet specification for matching a particular Servlet
based on its mapping(s). Basically, it first checks for an exact match, then it tries to do path matching (patterns like /something/*
), then it does extension mapping, and finally, if no matches were found, uses the default servlet, a servlet mapped to /
. In this case, your DispatcherServlet
(which runs the Spring MVC stack) is mapped to /
, so it is the default servlet.
When you send your request to
local:8080/myspringmvc/home.jsp
the path satisfies the extension mapping of *.jsp
and therefore the container uses the JspServlet
to handle the request. This JspServlet
tries to find an appropriate resource, but doesn't. Remember that JSPs inside WEB-INF
are not accessible publicly/externally. It therefore returns a 404.
When you send your request to
local:8080/myspringmvc/
the default servlet is chosen because nothing else can match that path. The DispatcherServlet
looks up its handlers and finds
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model) {
logger.info("Welcome home! The client locale is {}.");
return "home";
}
By returning the view name home
and because you've registered the appropriate InternalResourceViewResolver
, Spring will do a RequestDispatcher#forward(..)
to that JSP. That request will again be matched by the Servlet container, but this time, to the JspServlet
. Because this is an internal call (and the path is right), the request will be completed.
Similarly, for /stylechoosertable.jsp
, the JspServlet
is chosen before your DispatcherServlet
could do anything about it.
It doesn't throw any
org.springframework.web.servlet.PageNotFound
errors when I go to home.jsp or stylechoosertable.jsp, so I know the mapping is there.
The DispatcherServlet
is never involved, so it doesn't have the chance to log anything.
Upvotes: 2
Reputation: 4792
Well I don't think I am able to get your question properly, still if you want to have simple navigation function from home.jsp, i.e on click of the link, it should go to stylechoosertable.jsp, then a definite solution would be just have a link like
<a href="stylechoosertable">SomeName</a>
Now simply map this in controller
@RequestMapping(value = "/stylechoosertable")
public String goToSCT() {
return "stylechoosertable";
}
And if there is any stylechoosertable.jsp available in /WEB-INF/views/, it will simply get called.
Second Question the reason behind local:8080/myspringmvc/
working, not local:8080/myspringmvc/home.jsp
is basically lack of RequestMapping
for /home.jsp
, where as for the root URL i.e /
, a mapping is there in HomeController
Upvotes: 2