[Servlet]请求URI

1. 请求URI简介:

    1) 请求URI就是URL中域名之后和请求参数之前的部分,比如:http://localhost:8080/ServletSets/test1.view?name=Tom&id=89中,请求URI就是/ServletSets/test1.view;

    2) 请求URI决定了Web容器调用哪个具体的Servlet来响应请求,具体做法是Web容器用各个Servlet的URL模式来匹配请求URI中的内容,选择一个最合适的Servlet进行响应;

    3) 请求URI的组成:requestURI = contextPath + servletPath + pathInfo

         i. contextPath:即环境路径,即Servlet所在的应用程序环境根目录,比如servlet1放在目录ServletSets下,则contextPath就是/ServletSets;

         ii. servletPath:即Servlet路径,即Servlet的URL模式指定的路径,比如@WebServlet("/test1/*"),则如果选中该Servlet则servletPath就是/test1;

         iii. pathInfo:路径信息,即请求URI中除了环境路径和Servlet路径之外的路径,一般是URL模式后跟着的额外信息,比如上例中如果输入的URI是/test1/abc.view,则pathInfo就是/abc.view;

!!可以用HttpServletRequest的getRequestURI、getContextPath、getServletPath、getPathInfo来分别获取,三个分解后(即使用者四个函数获取后)得到的各个部分要没为null(空)要么必须以/打头!!


2. 不同URL模式对应的请求URI:

    1) 这里用一个程序来测试不同URL模式对应的请求URI都是怎么样的,这里只展示doGet方法的模板:

protected void doGet(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
	// TODO Auto-generated method stub
	// response.getWriter().append("Served at:
	// ").append(request.getContextPath());

	PrintWriter out = response.getWriter();
	out.println("<html>");
	out.println("<head>");
	out.println("<title>Servlet Pattern</title>");
	out.println("</head>");
	out.println("<body>");
	out.println("URI = " + request.getRequestURI() + "<br>");
	out.println("Context Path = " + request.getContextPath() + "<br>");
	out.println("Servlet Path = " + request.getServletPath() + "<br>");
	out.println("Path Info = " + request.getPathInfo() + "<br>");
	out.println("</body>");
	out.println("</html>");
	out.close();
}
!唯一要改变的地方就是@WebServlet的参数,用不同的URL模式来测试!

!!测试的URL为:http://localhost:8080/ServletSets...

!!因此contextPath始终都是/ServletSets

!!...就是不同的输入

!!接下来的测试都是围绕着...的不同来展开的

!!测试格式:[... :servletPath,pathInfo

    2) 路径映射:

         i. 模式:以/开头以/*结尾,两者中间不能为空,例如“/test/*”,所有以/test/开头或者是/test的...都会调用该Servlet;

         ii. 测试:模式为"/test/*"

/test : /test,null

/test/ :/test,/

/test/abc.view : /test,/abc.view

    3) 扩展映射:

         i. 模式:以*.开头,但是*.之后不能为空,例如"*.view",所有以.view结尾的...都会调用该Servlet;

         ii. 测试:模式为"*.view"

/xxx.view : /xxx.view,null  // 由于通配符是在前面,所以pathInfo一定是null

    4) 环境根目录映射:

         i. 模式:空字符串“”,即只有当...为空或者/时才能请求到该Servlet,就好像改Servlet是环境根(目录)一样;

         ii. 测试:模式为""

空 : "",/

/ : "",/

!!注意servletPath是""空字符串而不是null,再次验证了servletPath是跟随URL Pattern的,因为环境根目录映射的模式就是"",所以servletPath一定是"";

!!注意pathInfo是有的,即一个/,这个非常特殊,需要记忆!

    5) 完全匹配:

         i. 模式:不含通配符*,也不是环境根目录映射的其余映射,不能只含有一个/,因此必须以/打头,例如"/test.view",则必须...完全和/test.view一样才能调用该Servlet;

         ii. 测试:模式为"test.view"

/test.view : /test.view,null   // 由于为尾部无通配符,因此pathInfo必定为null

    6) 默认映射/预设Servlet:

         i. 模式:仅包含一个/,如果以上所有的方式都无法匹配上就调用该Servlet,但是...必须以/开头;

         ii. 测试:模式为"/"

/abcdefg.xxx : /abcdefg.xxx,null   // servlet为整个...,但是pathInfo为null,比较特殊,需要记忆

    7) 匹配冲突:即当一个URL可以匹配上多个模式的时候Web容器该如何选择?Web容器会使用贪心法选择,和正则表达式的贪心匹配本质相同,即最大匹配原则,会先匹配完全匹配模式,如果能匹配上就调用那个模式的Servlet,如果没有一个能匹配上就再和有通配符的模式进行匹配,然后选除了统配符以外能匹配上最多字符的那个模式所代表Servlet进行响应;


### Servlet 中实现请求重定向的方式 在 Java Web 开发中,Servlet 可以通过两种主要方式来实现请求的重定向:**请求转发 (Forward)** 和 **HTTP 重定向 (Redirect)**。 #### HTTP 重定向 `HttpServletResponse` 接口中提供了 `sendRedirect()` 方法用于实现 HTTP 重定向。此方法会向客户端发送一个状态码为 302 的响应,并告知浏览器访问一个新的 URL[^5]。如果指定的是相对路径,则 Servlet 容器会自动将其转换为绝对路径。 以下是使用 `sendRedirect()` 方法的一个简单示例: ```java protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置新的目标地址 String redirectUrl = "/newLocation"; // 使用 sendRedirect 进行重定向 response.sendRedirect(redirectUrl); } ``` 上述代码片段展示了如何利用 `sendRedirect()` 方法将用户的请求从当前 Servlet 转移到 `/newLocation` 地址上。 #### 请求转发 另一种实现方式是通过 `RequestDispatcher` 对象来进行请求转发。这种方式属于服务器端的行为,不会被客户端察觉。当某个 Servlet 处理完部分逻辑之后可以调用 `forward()` 方法把控制权交给另一个资源继续处理[^2]。 下面是一个关于请求转发的例子: ```java protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取 RequestDispatcher 实例 RequestDispatcher dispatcher = request.getRequestDispatcher("/anotherServlet"); // 将请求和响应对象传递给下一个组件 dispatcher.forward(request, response); } ``` 在这个例子中,原始请求的数据会被保留并传送到名为 `/anotherServlet` 的新位置进行进一步操作[^1]。 需要注意的是,在执行 `forward()` 或者 `include()` 后不能再尝试写入任何数据到输出流;而采用 `sendRedirect()` 则允许设置一些额外的信息比如查询字符串等附加参数[^4]。 --- ### 总结 对于简单的页面跳转或者需要改变 URI 显示的情况适合选用 `sendRedirect()` 来做外部可见的重定向动作;而对于希望保持原有上下文环境不变且不需要通知客户程序变化的情形下则更适合运用内部机制如 `RequestDispatcher` 执行 forward 动作。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值