重定向与请求转发的区别
重定向Redirect的原理
重定向方法
//下列代码中涉及路径问题,在后文讨论
response.sendRedirect("index.jsp");
response.sendRedirect("/index.jsp");
重定向的处理流程
- 接受客户端的http请求
- 在接受请求的Servlet中调用sendRedirect()方法
- 服务器发回包含3xx状态码和目标资源URL的response
- 客户端浏览器读取到3xx状态码,再次发送新的请求到目标URL
p.s. 有关重定向3xx状态码和重定向种类请参阅MDN
请求转发RequestDispatch的原理
请求转发方法
request.getRequestDispatcher("index.jsp").forward(request, response);
请求转发的处理流程
- 接受客户端的http请求
- 在Servlet中调用forward()方法将请求转发到另一个URL(jsp/servlet)
- jsp/servlet处理请求,并将响应发给客户端(此时请求路径依然是上一个Servlet)
比较
- 重定向在客户端生效,而请求转发作用在服务器
- 重定向中客户端发送两次Request请求,第一次发送给目标Sevlet,目标Servlet发回3xx状态码和重定向URL,第二次发送给重定向URL
- 请求转发中客户端发送一次Request请求,目标Servlet将该请求转发给另一个jsp/servlet,另一个servlet/jsp发回响应报文
- 重定向时客户端地址栏的请求路径会发生变化,而请求转发不会,因为客户端并不知道响应报文是由另一个jsp/servlet发回的
重定向与请求转发的路径问题
区分绝对路径与相对路径
C:/Windows/System32/cmd.exe 就是cmd.exe的绝对路径,假设当前处于C:/Windows路径下,那么cmd.exe的相对路径就是./System32/cmd.exe,其中 . 代表当前目录( … 代表当前目录的上一级目录)
假定当前项目的结构是这样的
|---web
|---admin
| |--loginFail.jsp
| |--loginSuccess.jsp
|---index.jsp
|---test.jsp
|---WEB-INF
|---LoginServlet.java
需要理清的问题是localhost:port代表的是**服务器地址*,在讨论路径问题时不需要讨论它,其后的路径才是真正的访问路径。
重定向路径问题
//假定当前地址处于module_name/test.jsp
//这代表着 [localhost:port]/module_name/index.jsp
response.sendRedirect("index.jsp");
//这代表着 [localhost:port]/index.jsp, 发回状态码404
response.sendRedirect("/index.jsp");
//正确的绝对路径应该是
response.sendRedirect("/module_name/index.jsp");
//你也可以使用,附带了服务器地址及协议,更加“绝对”
response.sendRedirect("http://localhost:port/module_name/index.jsp");
//那么,同理你也可以转到其他服务器,例如百度
response.sendRedirect("http://www.baidu.com/");
//使用 “/” 的路径代表绝对路径
//不使用 "/" 的路径代表相对路径,module_name代表项目名
请求转发路径问题
//假定当前地址处于module_name/index.jsp
//这代表着 [localhost:port]/module_name/admin/loginSuccess.jsp
request.getRequestDispatcher("admin/loginSuccess.jsp").forward();
//这代表着[localhost:port]/module_name/admin/loginSuccess.jsp
request.getRequestDispatcher("/admin/loginSuccess.jsp").forward();
//这代表着[localhost:port]/module_name/module_name/admin/loginSuccess.jsp,发回状态码404
request.getRequestDispatcher("/module_name/admin/loginSuccess.jsp").forward();
/*
*可以发现使用绝对路径时,加上项目名反而404了
*这是因为请求转发是在服务器上进行的
*所以绝对路径前置地址是 [domain/ip]:port/module_name
*/
/*
*到这里就可以看出来了
*使用绝对路径时前置地址即服务器地址
*即[domain/ip]:port/[AbsoluteURL]
*使用相对地址时则前置地址为当前所在目录
*即 :[domain/ip]:port/./[URL]
*
*例如当前处于localhost:port/module_name/admin/loginSuccess.jsp
*那么重定向或者请求转发回localhost:port/module_name/index.jsp
*相对路径为: ../index.jsp
*绝对路径为: /module_name/index.jsp(重定向)
* /index.jsp(请求转发)
*/
使用过滤器Filter拦截未登录请求
Filter是什么
Filter意指过滤器,用于处理用户的非法请求,比如上文中,如果没有过滤器,那么用户在地址栏中输入[domain/ip]:port/module_name/admin/loginSuccess.jsp,就能直接未登录访问loginSuccess.jsp。
Filter是怎么起作用的
Filter需要过滤的路径在DD(web.xml)文件中进行配置。当客户端要访问admin/loginSuccess.jsp时会先执行LoginFilter中的doFilter()方法对请求进行验证。下面实现一个简单的过滤器当用户通过修改地址栏路径访问loginSuccess.jsp时将用户重定向回index.jsp
实现LoginFilter类
@WebFilter(filterName = "LoginFilter")
public class LoginFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//请求路径 localhost:port/module_name/admin/*.jsp
String currentURL = request.getRequestURI();
//项目路径 localhost:port/module_name
String contextURL = request.getContextPath();
//访问路径 = 请求路径 - 项目路径 = /admin/*.jsp
String targetURL = currentURL.substring(contextURL.length());
if(targetURL.equals("/login")){
System.out.println("Login is legal. Your currentURL is " + currentURL);
chain.doFilter(request, response);
}else{
System.out.println("Login is illegal. Your currentURL is " + targetURL);
//因为请求路径是[localhost:port]/module_name/admin/*.jsp
//所以当前所处目录是 module_name/admin,重定向使用相对路径为../index.jsp
response.sendRedirect("../index.jsp");
}
}
public void init(FilterConfig config) throws ServletException {
}
}
DD中Filter的设置
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.web.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>