Spring MVC 在 JSP 中的请求URL。

23

我正在使用Spring MVC编写Web应用程序。 我正在为控制器使用注释等。除了应用程序中的实际链接(表单操作,<a>标记等)之外,一切都运行良好。目前,我的代码如下(显然是缩写版):

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

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

当我直接输入URL,比如“http://localhost:8080/MyApp/admin/listPeople”时,页面能够正确加载。然而,上面的链接却无法工作,它丢失了应用程序名称“MyApp”。

有人知道是否可以配置Spring将应用程序名称添加到其中吗?

如果需要查看我的Spring配置,请告诉我。我正在使用标准调度servlet和视图解析器等。


2
这在Spring 3.0中是可能的,使用<a href="<spring:url value="/admin/listPeople"/>">People</a> - tterrace
7个回答

50

你需要在链接前加上上下文路径。

// 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>

+1 谢谢,我也考虑过这种方法,但我更倾向于以某种方式使用Spring实现。 - Snowy Coder Girl
2
没有“Spring”的做法 :) 除了将${contextPath}添加到您的链接之前,唯一可以节省您的选项是将应用程序部署为根,以便其上下文路径为“/”(如Kevin所述); 但我不建议采用这种方法,因为它会使您的应用程序依赖于其部署。 - craftsman
我正在研究是否使用过滤器可以帮助实现这一目标。例如,使用RequestDispatcher。 - Snowy Coder Girl
我将把这个问题重新表述得更加通用。经过进一步检查,我同意应用程序(和Spring)无法解决这个问题。希望将问题定位于服务器方向能够有所帮助。 - Snowy Coder Girl
使用contextPath和spring:url有什么区别吗? - vault
显示剩余2条评论

14

c:url 标签会在您的 URL 后追加上下文路径。例如:

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

在我的Spring MVC应用中,我更喜欢尽可能使用相对URL。 所以如果页面在/MyApp/index位置,链接<a href="admin/listPeople">将带我到listPeople页面。

如果您在URL层次结构中深入了更多级别,这也同样适用。 您可以使用..返回上一级。 因此,在位于/MyApp/admin/people/aPerson的页面上,使用<a href="../listPeople">将返回到列表页面。


6

我更喜欢使用BASE标签:

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

然后,你所有的链接可以像这样:
<a href="admin/listPeople">Go to People List</a>

在使用基础标签之前,我建议先阅读这篇文章:https://dev59.com/enI-5IYBdhLWcg3wYXL8 - Amr Mostafa

4

我刚刚尝试寻找答案,这是谷歌的第一个结果。

现在可以使用MvcUriComponentsBuilder完成此操作。

这是Spring MVC 4.0版本的一部分。

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

所需方法是fromMappingName。

从文档中:

从Spring MVC控制器方法的请求映射名称创建URL。 在启动时,配置的HandlerMethodMappingNamingStrategy确定控制器方法请求映射的名称。默认情况下,所有映射都基于类名的大写字母分配名称,后跟“#”作为分隔符,然后是方法名。例如,对于名为PersonController的类和方法getPerson,“PC#getPerson”。如果命名约定未产生唯一结果,则可以通过@RequestMapping注释的name属性分配显式名称。

这主要用于视图呈现技术和EL表达式。 Spring URL标记库将此方法注册为名为“mvcUrl”的函数。

例如,给定此控制器:

@RequestMapping("/people")
 class PersonController {

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

 }

一个 JSP 可以如下准备一个 URL 给 controller 方法:
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>

 <a href="${s:mvcUrl('PC#getPerson').arg(0,"123").build()}">Get Person</a>

0
你可以使用servletRelativeAction。我不确定这个版本可用(我目前正在使用4.0.x),并且我没有看到太多关于此的文档,但是如果您查看支持Spring表单的代码,您可能会猜到。只需确保您传递的路径以“/”开头即可。
例如:
<form:form class="form-horizontal" name="form" servletRelativeAction="/j_spring_security_check"  method="POST">

请参考 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.");
        }
    }
}

0

我通常会配置Tomcat使用根目录“/”或将war文件部署为ROOT.war。无论哪种方式,war文件的名称都不会成为URL的一部分。


-1

既然已经过了几年,我想为那些寻找答案的人做出一点贡献。 如果你正在使用注解,并且有一个像这样的控制器动作:

@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;
}

在你的 .jsp(视图)中添加这个指令。
<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>

并简单使用

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

在哪里

value 的值应该与控制器操作中 @RequestMapping 的参数匹配,

var 的值是您用于 href 的变量名称

HIH


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接