Spring MVC Request URLs in JSP
Asked Answered
F

7

23

I am writing a web application using Spring MVC. I am using annotations for the controllers, etc. Everything is working fine, except when it comes to actual links in the application (form actions, <a> tags, etc.) Current, I have this (obviously abbreviated):

//In the controller
@RequestMapping(value="/admin/listPeople", method=RequestMethod.GET)

//In the JSP
<a href="/admin/listPeople">Go to People List</a>

When I directly enter the URL like "http://localhost:8080/MyApp/admin/listPeople", the page loads correctly. However, the link above does not work. It looses the application name "MyApp".

Does anyone know if there is a way to configure Spring to throw on the application name on there?

Let me know if you need to see any of my Spring configuration. I am using the standard dispatcher servlet with a view resolver, etc.

Frasier answered 7/8, 2011 at 1:24 Comment(1)
This is possible in spring 3.0 with <a href="<spring:url value="/admin/listPeople"/>">People</a>Anemometry
I
50

You need to prepend context path to your links.

// somewhere on the top of your JSP
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>

...
<a href="${contextPath}/admin/listPeople">Go to People List</a>
Insensibility answered 7/8, 2011 at 1:28 Comment(7)
+1 Thanks, I thought of this but I'd rather do it with Spring somehow.Frasier
There is no "Spring" way of doing this :) Only option that saves you from prepending ${contextPath} to your links is that you deploy your application as root, so that it's context path is "/" (as Kevin has described); but I would not recommend this approach because it will make your application dependent of its deployment.Insensibility
I am looking into whether a filter would help accomplish this. Like, using a RequestDispatcher.Frasier
I don't think so. Your filters reside in your application and they can process only those requests which are sent to your application. If a request does not have the correct context path (MyApp in your case), servlet container will not send it to your application at all.Insensibility
Dang. Well <c:url> works for the links, but still not as nice as I'd like. I'd like an automatic way to apply it to the whole app. I know it's somehow possible (my old work did it). We used straight on "/admin/listPeople" and stuff. And sometimes just "listPeople".Frasier
I am going to rephrase this question as more generic. I agree on further inspection that the application (and Spring) cannot solve this. Hopefully making the question server oriented would help.Frasier
Is there any difference in using contextPath instead of spring:url?Jovita
B
14

The c:url tag will append the context path to your URL. For example:

<c:url value="/admin/listPeople"/>

Alternately, I prefer to use relative URLs as much as possible in my Spring MVC apps as well. So if the page is at /MyApp/index, the link <a href="admin/listPeople"> will take me to the listPeople page.

This also works if you are deeper in the URL hierarchy. You can use the .. to traverse back up a level. So on the page at/MyApp/admin/people/aPerson, using <a href="../listPeople"> will like back to the list page

Buchmanism answered 14/8, 2011 at 5:17 Comment(0)
R
6

I prefer to use BASE tag:

<base href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/" />

Then, all your links can be like:

<a href="admin/listPeople">Go to People List</a>
Radiotelegram answered 8/8, 2011 at 11:39 Comment(1)
I advise to read this before using the base tag: #1889576Arevalo
A
4

As i have just been trying to find the answer to this question and this is the first google result.

This can be done now using the MvcUriComponentsBuilder

This is part of the 4.0 version of Spring MVC

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.html

The method needed is fromMappingName

From the documentation :

Create a URL from the name of a Spring MVC controller method's request mapping. The configured HandlerMethodMappingNamingStrategy determines the names of controller method request mappings at startup. By default all mappings are assigned a name based on the capital letters of the class name, followed by "#" as separator, and then the method name. For example "PC#getPerson" for a class named PersonController with method getPerson. In case the naming convention does not produce unique results, an explicit name may be assigned through the name attribute of the @RequestMapping annotation.

This is aimed primarily for use in view rendering technologies and EL expressions. The Spring URL tag library registers this method as a function called "mvcUrl".

For example, given this controller:

@RequestMapping("/people")
 class PersonController {

   @RequestMapping("/{id}")
   public HttpEntity getPerson(@PathVariable String id) { ... }

 }

A JSP can prepare a URL to the controller method as follows:

<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>

 <a href="${s:mvcUrl('PC#getPerson').arg(0,"123").build()}">Get Person</a>
Aggappera answered 19/7, 2016 at 15:28 Comment(0)
S
0

I usually configure tomcat to use context root of "/" or deploy the war as ROOT.war. Either way the war name does not become part of the URL.

Sunbonnet answered 7/8, 2011 at 1:30 Comment(0)
A
0

You could use a servletRelativeAction. I'm not sure what versions this is available in (I'm using 4.0.x currently) and I haven't seen much documentation on this, but if you look at the code backing the spring form you can probably guess. Just make sure the path you pass it starts with a "/".

Example:

<form:form class="form-horizontal" name="form" servletRelativeAction="/j_spring_security_check"  method="POST">

See org.springframework.web.servlet.tags.form.FormTag:

protected String resolveAction() throws JspException {
    String action = getAction();
    String servletRelativeAction = getServletRelativeAction();
    if (StringUtils.hasText(action)) {
        action = getDisplayString(evaluate(ACTION_ATTRIBUTE, action));
        return processAction(action);
    }
    else if (StringUtils.hasText(servletRelativeAction)) {
        String pathToServlet = getRequestContext().getPathToServlet();
        if (servletRelativeAction.startsWith("/") && !servletRelativeAction.startsWith(getRequestContext().getContextPath())) {
            servletRelativeAction = pathToServlet + servletRelativeAction;
        }
        servletRelativeAction = getDisplayString(evaluate(ACTION_ATTRIBUTE, servletRelativeAction));
        return processAction(servletRelativeAction);
    }
    else {
        String requestUri = getRequestContext().getRequestUri();
        ServletResponse response = this.pageContext.getResponse();
        if (response instanceof HttpServletResponse) {
            requestUri = ((HttpServletResponse) response).encodeURL(requestUri);
            String queryString = getRequestContext().getQueryString();
            if (StringUtils.hasText(queryString)) {
                requestUri += "?" + HtmlUtils.htmlEscape(queryString);
            }
        }
        if (StringUtils.hasText(requestUri)) {
            return processAction(requestUri);
        }
        else {
            throw new IllegalArgumentException("Attribute 'action' is required. " +
                    "Attempted to resolve against current request URI but request URI was null.");
        }
    }
}
Addlebrained answered 1/2, 2014 at 2:2 Comment(0)
D
-1

Since it's been some years I thought I'd chip in for others looking for this. If you are using annotations and have a controller action like this for instance:

@RequestMapping("/new")   //<--- relative url
public ModelAndView newConsultant() {
    ModelAndView mv = new ModelAndView("new_consultant");
    try {
        List<Consultant> list = ConsultantDAO.getConsultants();
        mv.addObject("consultants", list);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return mv;
}

in your .jsp (view) you add this directive

<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>

and simply use

<spring:url value="/new" var="url" htmlEscape="true"/>
<a href="${url}">New consultant</a>

where

value's value should match @RequestMapping's argument in the controller action and

var's value is the name of the variable you use for href

HIH

Dannielledannon answered 24/9, 2018 at 5:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.