<转载>SpringMVC(6):${pageContext.request.contextPath}的使用 与 绝对路径/相对路径的使用区别

2018/1/8

<import name="转载1" value="http://931360439-qq-com.iteye.com/blog/954571" >

<import name="转载2" value="https://www.cnblogs.com/langtianya/archive/2013/03/04/2942515.html">

一.问题 


       JSP中究竟采用绝对路径还是采用相对路径随着所采用技术的越来越复杂,这个问题也变得越来越难以解决。
1)采用相对路径遇到的问题
相对路径固然比较灵活,但如果想复制页面内的代码却变得比较困难,因为不同的页面具有不同的相对路径,复制后必须修改每一个连接的路径。
如果页面被多于一个的页面所包含,那么被包含页面中的相对路径将是不正确的。
如果采用Struts的Action返回页面,那么由于页面路径与Action路径不同,使得浏览器无法正确解释页面中的路径,如页面为/pages/cust/cust.jsp,图片所有目录为/images/title.gif,这时在/pages/cust/cust.jsp中的所用的路径为”http://images.cnblogs.com/title.gif”,但是如果某一个Action的Forward指向这个JSP文件,而这个Action的路径为/cust/manage.do,那么页面内容中”http://images.cnblogs.com/title.gif”就不再指向正确的路径了。
解决以上问题似乎只有使用绝对路径了。

2)采用绝对路径遇到的问题
随着不同的Web应用发布方式,绝对路径的值也不同。如Web应用发布为MyApp,则路径”/MyApp/images/title.gif”是正确的,但发布为另一应用时如MyApp2,这个路径就不对了,也许这个情况比较少,但以default方式发布Web应用时以上绝对路径也不同:”/images/title.gif”。

 

二.解决方案 

 


1)采用绝对路径,但为了解决不同部署方式的差别,在所有非struts标签的路径前加${pageContext.request.contextPath},如原路径为:
”/images/title.gif”,改为
“${pageContext.request.contextPath}/images/title.gif”。
代码” ${pageContext.request.contextPath}”的作用是取出部署的应用程序名,这样不管如何部署,所用路径都是正确的。

缺点:
操作不便,其他工具无法正确解释${pageContext.request.contextPath}
2) 采用相对路径,在每个JSP文件中加入base标签,如:
<base href="http://${header['host']}${pageContext.request.contextPath}/pages/cust/relation.jsp" />
这样所有的路径都可以使用相对路径。

缺点:
对于被包含的文件依然无效。
真正使用时需要灵活应用1)和2),写出更加健壮的代码。

在使用的时候可以使用${pageContext.request.contextPath},也同时可以使用<%=request.getContextPath()%>达到同样的效果,同时,也可以将${pageContext.request.contextPath},放入一个JSP文件中,将用C:set放入一个变量中,然后在用的时候用EL表达式取出来。
eg:

 

<c:set var="ctx" value="${pageContext.request.contextPath}" /> 

 


三、通俗易懂的观点

 

     ${pageContext.request.contextPath} 等价于 <%request.getContextPath%>,或者可以说是<%request.getContextPath%>的EL版,<%request.getContextPath%>是JSP版!它们的意思就是取得当前项目名称(或者是--取出部署的应用程序名!这么说太官方了!试问有多少人知道“取出部署的应用程序名”的含义!不过我一看到这么说,头就大了!搞什么“孔乙己”啊!)
      什么是当前的项目名称呢?
      假定你的web application 名称为test,这个test就是当前的项目名称,不过你在浏览器中输入请求路径时,如:
http//:localhost:8080/test/hello.jsp
${pageContext.request.contextPath}或<%request.getContextPath%>就是从这个请求路径(URL)上截取(是截取)----> /test 看清楚,前面是有"/",而这个“/”代表的是-->"http//:localhost:8080",看清楚这里是没有"/"的!
      所以才有了网上那些文章写的,如果我们:
<form action="${pageContext.request.contextPath}/hello.jsp">这样写路径永远对,当然对了,因为你自己翻译${pageContext.request.contextPath}/hello.jsp其中的含义,不就是
http//:localhost:8080/test/hello.jsp 相当于你写了一全路径!当然前提是你的JSP页面等等必须放置的位置正确才可以---->所以才说明路径永远正确

       为什么这么要做呢?因为学过一些MVC模式的程序员都知道,JSP的作用是用来显示的(表现的),其他的作用最好不要在这个页面上显示,尤其是Java代码!所以就用EL表达式来替代类似有“<%%>”这样的代码格式

     最后我在说一句:用到${pageContext.request.contextPath}是在JSP页面上的! 


欢迎扫二维码关注公众号,获取技术干货

 

(一)项目构建 使用 Maven 构建项目,在pom.xml中引入 Spring MVC 相关依赖,如spring - webmvc,配置 Servlet、JSP 等相关依赖,确保项目具备 Spring MVC 运行环境 。示例关键依赖配置: <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring - webmvc</artifactId> <version>5.3.18</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet - api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp - api</artifactId> <version>2.3.3</version> <scope>provided</scope> </dependency> <!-- 其他如JSTL等依赖按需添加 --> </dependencies> (二)Spring MVC 配置 DispatcherServlet 配置:在 Web.xml(或 Servlet 3.0 + 环境下用 Java 配置)中配置 DispatcherServlet,指定 Spring MVC 配置文件位置,使其能拦截处理请求 。示例 Web.xml 配置: <servlet> <servlet - name>springmvc</servlet - name> <servlet - class>org.springframework.web.servlet.DispatcherServlet</servlet - class> <init - param> <param - name>contextConfigLocation</param - name> <param - value>classpath:springmvc - servlet.xml</param - value> </init - param> <load - on - startup>1</load - on - startup> </servlet> <servlet - mapping> <servlet - name>springmvc</servlet - name> <url - pattern>/</url - pattern> </servlet - mapping> Spring MVC 配置文件(springmvc - servlet.xml):开启组件扫描(扫描控制器等组件)、视图解析器(配置前缀后缀,解析 JSP 视图)、开启注解驱动等 。示例: <context:component - scan base - package="com.example.controller"/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB - INF/views/"/> <property name="suffix" value=".jsp"/> </bean> <mvc:annotation - driven/> 三)功能模块实现 1. 用户登录验证 o 控制器(Controller):创建LoginController,编写方法处理/login请求(对应login.jsp表单提交),接收用户名、密码参数(可通过@RequestParam注解),进行简单验证(如硬编码用户名 “admin”、密码 “123” 模拟,实际可连数据库查询),验证成功用return "redirect:/main";重定向到主页控制器方法,失败则带错误信息(通过model.addAttribute)返回login视图(即login.jsp )。示例代码: package com.example.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class LoginController { @RequestMapping("/login") public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model) { if ("admin".equals(username) && "123".equals(password)) { return "redirect:/main"; } else { model.addAttribute("error", "用户名或密码错误"); return "login"; } } 2. 登录页面(login.jsp):使用 Spring 表单标签库(需引入相关标签库)或普通 HTML 表单,提交到/login,显示错误信息(通过 EL 表达式${error} )。示例关键代码: <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <html> <body> <form:form action="/login" method="post"> 用户名:<form:input path="username"/><br> 密码:<form:password path="password"/><br> <input type="submit" value="登录"> </form:form> <c:if test="${not empty error}"> <p style="color:red">${error}</p> </c:if> </body> </html> 3. 访问控制(拦截器实现) o 创建拦截器类:实现HandlerInterceptor接口,在preHandle方法中检查会话是否有用户登录标识(如session.getAttribute("user") ,假设登录成功时在会话存user对象),无则redirect到/login并返回false拦截,有则返回true放行 。示例: package com.example.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object user = request.getSession().getAttribute("user"); if (user == null) { response.sendRedirect(request.getContextPath() + "/login"); return false; } return true; } } 4. 配置拦截器:在 Spring MVC 配置文件(springmvc - servlet.xml)中注册拦截器,指定拦截路径(如/main )。示例: <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/main"/> <bean class="com.example.interceptor.LoginInterceptor"/> </mvc:interceptor> </mvc:interceptors> 5. 会话管理(登出功能) o 控制器方法:在MainController中编写处理登出的方法,调用session.invalidate()销毁会话,然后redirect到登录页 。示例: package com.example.controller; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class MainController { @RequestMapping("/main") public String main() { return "main"; } @RequestMapping("/logout") public String logout(HttpSession session) { session.invalidate(); return "redirect:/login"; } } 6. 主页(main.jsp):添加 “退出” 链接, href 指向/logout 。示例: <html> <body> <h1>欢迎访问主页</h1> <a href="${pageContext.request.contextPath}/logout">退出</a> </body> </html>
06-05
<%-- Created by IntelliJ IDEA. User: vili Date: 2019/8/23 Time: 13:42 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@page isELIgnored="false" %> <!--header--> <div class="header"> <div class="container"> <nav class="navbar navbar-default" role="navigation"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <h1 class="navbar-brand"><a href="index.action">叮当书城</a></h1> </div> <!--navbar-header--> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li><a href="index.action" <c:if test="${param.flag==1}">class="active"</c:if>>首页</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle <c:if test="${param.flag==2}">active</c:if>" data-toggle="dropdown">商品分类<b class="caret"></b></a> <ul class="dropdown-menu multi-column columns-2"> <li> <div class="row"> <div class="col-sm-12"> <h4>商品分类</h4> <ul class="multi-column-dropdown"> <li><a class="list" href="booktypes_list.action?pageNumber=1&btid=-1">全部系列</a></li> <c:forEach items="${bookTypes}" var="t"> <li><a class="list" href="booktypes_list.action?pageNumber=1&btid=${t.btid}">${t.btname}</a></li> </c:forEach> </ul> </div> </div> </li> </ul> </li> <li><a href="recommend_books.action?rtype=2&pageNumber=1" <c:if test="${param.flag==3 && t==2}">class="active"</c:if>>热销</a></li> <li><a href="recommend_books.action?rtype=3&pageNumber=1" <c:if test="${param.flag==3 && t==3}">class="active"</c:if>>新品</a></li> <c:choose> <c:when test="${empty user }"> <li><a href="user_register.jsp" <c:if test="${param.flag==10 }">class="active"</c:if>>注册</a></li> <li><a href="user_login.jsp" <c:if test="${param.flag==9 }">class="active"</c:if>>登录</a></li> </c:when> <c:otherwise> <li><a href="order_list.action" <c:if test="${param.flag==5 }">class="active"</c:if>>我的订单</a></li> <li><a href="user_center.jsp" <c:if test="${param.flag==4 }">class="active"</c:if>>个人中心</a></li> <li><a href="logout.action" >退出</a></li> <li><a href="admin/index.jsp" target="_blank">后台管理</a></li> </c:otherwise> </c:choose> </ul> <!--/.navbar-collapse--> </div> <!--//navbar-header--> </nav> <div class="header-info"> <div class="header-right search-box"> <a href="javascript:;"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></a> <div class="search"> <form class="navbar-form" action="search_books.action"> <input type="hidden" name="pageNumber" value="1"/> <input type="text" class="form-control" name="keyword"> <button type="submit" class="btn btn-default <c:if test="${param.flag==7 }">active</c:if>" aria-label="Left Align">搜索</button> </form> </div> </div> <div class="header-right cart"> <a href="book_cart.jsp"> <span class="glyphicon glyphicon-shopping-cart <c:if test="${param.flag==8 }">active</c:if>" aria-hidden="true"><span class="card_num"><c:choose><c:when test="${empty order}">0</c:when><c:otherwise>${order.itemMap.size()}</c:otherwise></c:choose></span></span> </a> </div> <div class="clearfix"> </div> </div> <div class="clearfix"> </div> </div> </div> <!--//header-- 修改代码使后台管理标签能跳转到后台管理页面
06-20
创建Web项目,导入相关JAR包; <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency> 创建并配置web.xml文件; <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>Springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:SpringMVC.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> 添加用于上传的jsp页面; <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html> <html> <head> <title>文件上传</title> </head> <body> <table border="1"> <tr> <td width="500" align="center">文件上传</td> </tr> <tr> <td> <form action="${pageContext.request.contextPath}/file/upload" method="post" enctype="multipart/form-data"> <input type="file" name="uploadfiles" multiple="multiple"/><br> <input type="submit" value="上传"><br> </form> </td> </tr> <c:forEach items="${msgs}" var="msg"> <tr><td align="center" colspan="2" style="color: red">${msg}</td></tr> </c:forEach> </table> </body> </html> 创建控制类用于上传文件; package com.springmvc.controller; import java.io.File; import java.io.IOException; import java.util.ArrayList; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.multipart.MultipartFile; @Controller @RequestMapping("/file") public class FileUploadController { @RequestMapping("/upload") public String fileUpload(ArrayList<MultipartFile> uploadfiles, HttpServletRequest request) { //定义列表msgs保存提示信息 ArrayList<String> msgs = new ArrayList<>(); if (uploadfiles.get(0).getSize() > 0) { //判断是否上传文件 for (MultipartFile file : uploadfiles) { //循环获取文件 //判断文件不为空且大小大于0 if (!file.isEmpty() & file.getSize() > 0) { //获取文件原始名称 String originalFilename = file.getOriginalFilename(); //获取服务器中的文件夹路径 String path = request.getServletContext().getRealPath("/upload/"); //设置文件保存到服务器的目标路径 String filePath = path + originalFilename; try { //保存文件内容到目标路径 file.transferTo(new File(filePath)); } catch (IOException e) { msgs.add(filePath + "保存失败"); } msgs.add(filePath +"保存成功"); } } } else msgs.add("上传文件失败"); request.setAttribute("msgs", msgs); return "fileUpload"; } } 添加配置文件; <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.springmvc.controller"/> <mvc:annotation-driven /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp"/> </bean> <!--配置视图控制器,指定文件上传页面的映射路径--> <mvc:view-controller path="/file/fileupload" view-name="fileUpload"/> <mvc:view-controller path="/file/filedownload" view-name="fileDownload"/> <!--配置注解驱动--> <mvc:annotation-driven/> <!--配置文件上传解析器--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--指定请求的编码方式--> <property name="defaultEncoding" value="UTF-8"></property> <!--指定允许上传文件的大小,此处设置最大值为1 M,单位为字节--> <property name="maxUploadSize" value="1024000"></property> </bean> </beans> 添加上传成功的消息页面。 文件下载: 创建控制器类: package com.springmvc.controller; import java.io.File; import java.io.IOException; import java.net.URLEncoder; import javax.servlet.http.HttpServletRequest; import org.apache.commons.io.FileUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/file") public class FileDownloadController { @RequestMapping("/download") public ResponseEntity<byte[]> FileDownload(HttpServletRequest request, String fileName) throws IOException { //获取下载文件的路径 String filepath = request.getServletContext().getRealPath("/upload/") + fileName; //创建该文件的对象 File file = new File(filepath); //将文件读取到字节数组中 byte[] bytes = FileUtils.readFileToByteArray(file); //创建HttpHeaders对象设置响应头信息 HttpHeaders headers = new HttpHeaders(); //设置浏览器以“UTF-8”编码方式显示文件名 fileName = URLEncoder.encode(fileName, "UTF-8"); //设置以下载的方式打开文件,并指定文件名称 headers.setContentDispositionFormData("attachment", fileName); //设置文件的下载方式为二进制流 headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); return new ResponseEntity<>(bytes, headers, HttpStatus.OK); } } 添加用于上传的jsp页面; <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <title>文件下载</title> </head> <body> <table border="1"> <tr> <td width="350" align="center">下载列表</td> </tr> <tr> <td> <a href="${pageContext.request.contextPath}/file/download?fileName=微信图片_20250612231528.jpg"> 这是一张图片</a><br> </td> </tr> </table> </body> </html> 实验成果: 修改一下
最新发布
11-01
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后台技术汇

对你的帮助,是对我的最好鼓励。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值