开发者

spring mvc forward to jsp

I currently have my web.xml configured to catch 404s and send them to my spring controller which will perform a search given the original URL request.

The functionality is all there as far as the catch and search go, however the trouble begins to arise when I try to return a view.

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver" p:order="1">
    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json" />
            <entry key="jsp" value="text/html" />
        </map>
    </property>

    <property name="defaultContentType" value="application/json" />
    <property name="favorPathExtension" value="true" />

    <property name="viewResolvers">
        <list>
            <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
            <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/WEB-INF/jsp/" />
                <property name="suffix" value="" />
            </bean>
        </list>
    </property>
    <property name="defaultViews">
        <list>
            <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
        </list>
    </property>
    <property name="ignoreAcceptHeader" value="true" />
</bean>

This is a snippet from my MVC config file.

开发者_StackOverflow社区

The problem lies in resolving the view's path to the /WEB-INF/jsp/ directory. Using a logger in my JBoss setup, I can see that when I test this search controller by going to a non-existent page, the following occurs:

  1. Server can't find the request

  2. Request is sent to 404 error page (in this case my search controller)

  3. Search controller performs search

  4. Search controller returns view name (for this illustration, we'll assume test.jsp is returned)

  5. Based off of server logger, I can see that org.springframework.web.servlet.view.JstlView is initialized once my search controller returns the view name (so I can assume it is being picked up correctly by the InternalResourceViewResolver)

  6. Server attempts to return content to browser resulting in a 404!

A couple things confuse me about this:

  1. I'm not 100% sure why this isn't resolving when test.jsp clearly exists under the /WEB-INF/jsp/ directory.

  2. Even if there was some other problem, why would this result in a 404? Shouldn't a 404 error page that results in another 404 theoretically create an infinite loop?

Thanks for any help or pointers!

Controller class [incomplete]:

@Controller
public class SiteMapController {

//--------------------------------------------------------------------------------------        
@Autowired(required=true)   
private SearchService search;

@Autowired(required=true)
private CatalogService catalog; 
//--------------------------------------------------------------------------------------

@RequestMapping(value = "/sitemap", method = RequestMethod.GET)
public String sitemap (HttpServletRequest request, HttpServletResponse response) {  
    String forwardPath = "";
    try {
        long startTime = System.nanoTime() / 1000000;
        String pathQuery = (String) request.getAttribute("javax.servlet.error.request_uri");

        Scanner pathScanner = new Scanner(pathQuery).useDelimiter("\\/");
        String context = pathScanner.next();
        List<ProductLightDTO> results = new ArrayList<ProductLightDTO>();
        StringBuilder query = new StringBuilder();
        String currentValue;
        while (pathScanner.hasNext()) {
            currentValue = pathScanner.next().toLowerCase();
            System.out.println(currentValue);
            if (query.length() > 0)
                query.append(" AND ");
            if (currentValue.contains("-")) {
                query.append("\"");
                query.append(currentValue.replace("-", " "));
                query.append("\"");
            }
            else {
                query.append(currentValue + "*");
            }
        }       

        //results.addAll(this.doSearch(query.toString()));

        System.out.println("Request: " + pathQuery);
        System.out.println("Built Query:" + query.toString());
        //System.out.println("Result size: " + results.size());     
        long totalTime = (System.nanoTime() / 1000000) - startTime;
        System.out.println("Total TTP: " + totalTime + "ms");

        if (results == null || results.size() == 0) {
            forwardPath = "home.jsp";
        }
        else if (results.size() == 1) {
            forwardPath = "product.jsp";
        }
        else {
            forwardPath = "category.jsp";
        }

    }
    catch (Exception ex) {
        System.err.println(ex);
    }

    System.out.println("Returning view: " + forwardPath);
    return forwardPath;
}
}


1 . I'm not 100% sure why this isn't resolving when test.jsp clearly exists under the /WEB-INF/jsp/ directory.

This is because you did configure your view resolver with suffix = "" so the file must be named test (no extension).

2 . Even if there was some other problem, why would this result in a 404? Shouldn't a 404 error page that results in another 404 theoretically create an infinite loop?

I'm pretty sure this's the result of some protection against the infinite redirect loop in spring MVC.

Note: in controllers, spring expect a view name as a result so test not test.jsp (or better, use ModelAndView)


I am posting this as answer because it is too long but it is probably not an answer.

http://localhost:8080/webapp/servlet-mapping-url/controller-mapping/method-mapping

if your controller's method which handles the request does not return a view name string or a view object or write directly to output stream, spring dispatcher should resolve the view name to /WEB-INF/jsp/controller-mapping/method-mapping.jsp

This means the jsp must be under a folder, named /WEB-INF/jsp/controller-mapping/. However, if a view name or view object is return by the controller method, spring dispatcher will uses that instead.

Ther are other many possible mapping combination but this is the most common one. If you could show your controller class, it will be easier.

Update

If you are using DefaultAnnotationHandlerMapping, you should always annotated your class with @RequestMapping(value = "/mapping-string"). Otherwise spring dispatcher will try to pick it up when nothing else is matched.

Since the controller is mapped, you will have to change the method mapping to value = {"", "/"}

For the returning view name, you don't need to put .jsp.

If the returning view name is home then the spring dispatcher will resolve to /WEB-INF/jsp/home.jsp

If the returning view name is path/home then the spring dispatcher will resolve to /WEB-INF/jsp/path/home.jsp

P.S. You used a word forwardPath but it isn't really a forward. It is just a view name.

@Controller
@RequestMapping(value = "/sitemap")
public class SiteMapController {

    @RequestMapping(value = {"", "/"}, method = RequestMethod.GET)
    public String sitemap (HttpServletRequest request, HttpServletResponse response) {  
            ...
            if (results == null || results.size() == 0) {
                forwardPath = "home";
            }
            else if (results.size() == 1) {
                forwardPath = "product";
            }
            else {
                forwardPath = "category";
            }
            ...
        return forwardPath;
    }
}


Try to set order for your ViewResolver. For Example:

@Bean
public ViewResolver getViewResolver(){
  InternalResourceViewResolver resolver = new InternalResourceViewResolver();
  resolver.setViewClass(JstlView.class);
  resolver.setPrefix("/WEB-INF/jsp/");
  resolver.setSuffix(".jsp");
  resolver.setOrder(1);
  return resolver;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜