Web服务器接收到客户端的http请求,其会对每一次的http请求分别创建应该代表请求的
request
对象,和一个代表响应的response
对象.request
是获取客户端提交的数据,response是向客户端提供数据.
request
请求由以下数据组成
GET
,POST
,PUT
,DELETE
等等Content-Type
,User-Agent
,Accept-Languge
response
响应包括以下几个数据
200 OK
,404Not Found
,500 Internal Server Error
等response
的响应头与request的请求头的数据类型是一致的,Content-Type
,User-Agent
,Accept-Languge
HttpServletRequest
和HttpServletResponse
分别是ServletReques
和ServletResponse
的子接口,Http接口是专门处理HTTP协议的接口
ServletReques
与ServletResponse
是Servlet API中的顶级接口,与HttpServletRequest
和HttpServletResponse
不同的是,前者是处理请求/响应的基本接口,其定义了多种请求/响应的接口可适用多种协议,不仅是HTTP请求
以下主要介绍对于
HttpServletRequest
四个应用方面,其中也借鉴了同平台创造者@Evan Liu
String getRequestURL()
:返回客户端发出请求的完整URLString getRequestURI()
:返回请求行中部分资源名String getQueryString()
:返回请求行中的参数部分String getRemoteAddr()
:返回发出请求的客户端的IP地址String getMethod()
获得客户机请求方式getContextPath()
:获取工程虚拟目录的名称Eg:
@WebServlet("/test")
public class MyHttpServlet01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(req.getRequestURL());
System.out.println(req.getRequestURI());
System.out.println(req.getQueryString());
System.out.println(req.getRemoteAddr());
System.out.println(req.getMethod());
System.out.println(req.getContextPath());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("执行POST请求业务逻辑");
}
String getHeaders(String var1)
:获取头信息的值,将其转化为一个字符串,var1
:请求头的名称,例如:
"Accept-Encoding"
,"User-Agent"
、"Content-Type"
等等
Enumeration<String> getHeaders(String var1)
:获取头信息的值,返回应该Enumeration<String>
类型的数组
Enumeration<String> getHeaderNames(String var1)
:获取所有头信息名称,返回应该Enumeration<String>
类型的数组
Enumeration
:枚举接口,是一种特殊的数据类型,主要用于遍历集合元素,是个较老的技术,现在主流使用Iterator
和Iterable
eg:
@WebServlet("/test")
public class MyHttpServlet01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("getHeaders:"+req.getHeaders("Accept-Encoding"));
//获取http请求头中的referer防盗链
System.out.println("getHeaders:"+req.getHeader("referer"));
System.out.println("--------------------------------------------------");
Enumeration<String> headerNames = req.getHeaderNames();
while(headerNames.hasMoreElements())
{
String name=headerNames.nextElement();
System.out.println(name+":"+req.getHeader(name));
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("执行POST请求业务逻辑");
}
}
String getParameter(String name)
:获取一个指定名称的请求参数的值,没找到则返回null
String getParameterValues(String name)
:获取指定名称的请求参数的所有值,即一个参数有多值,则返回所有,没找到则返回null
Enumeration<String> getParameterNames()
:获取请求中的所有参数名Map<String, String[]> getParameterMap()
:获取请求中的所有参数及其映射eg:
@WebServlet("/test")
public class MyHttpServlet01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String parameter = req.getParameter("value");
String[] values = req.getParameterValues("value");
Enumeration<String> parameterNames = req.getParameterNames();
Map<String, String[]> parameterMap = req.getParameterMap();
System.out.println(parameter);
System.out.println(Arrays.toString(values));
while(parameterNames.hasMoreElements())
{
String str=parameterNames.nextElement();
System.out.println(str);
}
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
String str = entry.getKey();
String[] string = entry.getValue();
System.out.print(str+":");
System.out.println(Arrays.toString(string));
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("执行POST请求业务逻辑");
}
}
在Java Web 请求转发是一个十分常用的技术,其用于在一个Web应用内部,从一个资源如(
Servlet
),跳转到另一个资源,实现资源的分布利用
请求转发的原理
Java中,提供了一个
RequestDispatcher
接口,用于实现请求转发和请求包含,这在处理复杂的Web应用逻辑时非常有用
RequestDispatcher的主要方法
void forward(ServletRequest var1,ServletResponse var2
:将当前请求转发到指定的目标资源,传递原始请求和响应对象void include(ServletRequest var1, ServletResponse var2)
:将指定的目标资源包含到当前响应中,目标资源的输出会被合并到当前响应中ServletRequest请求范围方法
Java Web开发中ServletRequest接口提供的方法可以让一些属性在一个请求的生命周期被多个资源共享
void setAttribute(String name, Object object)
:其用于将一个 <名称-对象> 对添加到请求范围,在之后的业务逻辑中使用
setAttribute
方法时,ServletRequest
接口会创建一个内部映射Map,将其<名称-对象>对添加在其中,该Map是一个线程安全的数据结构,适于存储范围属性setAttribute
存储的属性可以在处理不同阶段被多个资源访问,则意味着可以在不同的Servlet
之间共享数据Object getAttribute(String name)
:用于获取指定名称的请求属性的值,没有检索到则访问null
viod removeAttribute(String name)
:用于从请求范围中删除指定名称的属性HttpServletRequest
和HttpServletResponse
HttpServletResponse
封装服务器向客户端发送响应数据信息
void setStatus(int status)
:用于设置HTTP响应状态码,通常用于指示客户端是否成功以及如何处理响应,status
:HTTP响应状态码,如200 OK
和404 Not Found
void setHeader(String name, String value)
:设置一个带有给定名称和值的Header
,若name
已存在,则直接覆盖
ServletOutputStream getOutputStream()
:获取一个ServletOutputStream
字节流对象,输出响应体内容
PrintWriter getWriter()
:获取一个PrintWriter
字符流对象,输出响应体内容,PrintWriter
实际上继承了Writer
状态响应码
状态响应码用于表示服务器对客户端请求的响应状态,状态码都是有一个三位数字代码和一个简短的描述组成,状态码可分为五种:1xx,2xx,3xx4xx,5xx
1XX(信息状态码)
此类状态码表示请求已经被服务器接收,但仍需进一步处理
POST
请求,表示服务器告知客户端已经接收了一部分,客户端可以继续发送剩余部分2XX(成功协议)
此类状态码表示请求已经被成功处理
3XX(重定向状态码)
此类状态码表示客户端还要采用进一步操作来无参指示
301 Moved Permanently:表示服务器资源被永久性地转移到一个新的URL,客户端(浏览器)将自动地将资源重定向到新URL
302 Found (Previously "Moved Temporarily"):其表示请求的资源被暂时转移到一个新URL,同样客户端会自动将其资源重定向到新URL
4XX(客户端错误状态码)
此类状态码表示客户端的请求存在错误
5XX(服务器错误状态码)
重定位(Redirect)是一个常见的技术,用于将一个客户端请求从一个资源重定位到另一个资源,重定位与转发不同,重定位会创建一个新的HTTP请求
重定位的方式
在Servlet API中,
HttpServletResponse
接口提供了一个方法实现重定位
void sendRedirect(String location)
:将客户端重定位到相应的URL,location:目标URL地址eg:
@WebServlet("/test01")
public class MyHttpServlet01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置输出文字格式,即编码格式
resp.setContentType("text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.println("<p>这是第一个servlet</p>");
//进行转发到/test02
resp.sendRedirect("/test02");
}
}
//
@WebServlet("/test02")
public class MyHttpServlet02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.println("<p>这是第二个servlet</p>");
}
}
当向浏览器访问/test01时,浏览器会接受到第一个Servlet的响应,接着会重定位到/test02.再次发起请求,客户端会看到两次跳转和以下界面
重定位的原理
302 Found
(或301 Moved Permanently
)会查看其响应头(Response Headers)
中的Location属性,并根据其进行重定位sendRedirect()
实际是设置了请求头中的Status Code(状态响应码)和响应头中的Location属性转发和重定向都是实现页面的跳转,他们都是访问一个Servlet时,Servlet会帮我们跳转到另一个界面,只是实现方法不同,以下内容借鉴了创造者 @萌小Q
forward
是服务器请求资源,服务器之间访问目标地址的URL,服务器将目标URL响应内容发送给客户端(浏览器),实际上浏览器不知道服务器发送的内容是从哪里来的,其操作是服务器实现的redirect
是服务器根据业务逻辑发送一个状态码,告知浏览器重新去请求新的URL,因此重定位地址栏的URL会相应改变request
作用域里的数据redirect
:不能共享数据forward
:一般用于用户登录时,根据角色转发相应模板redirect
:一般用于用户注销登录时放回主页面或是跳转到其他网站等等forward
:较高效率redirect
:效率较低
forward
(转发)是服务器行为,redirect
(重定向)是客户端行为
forward
行为:客户端(Browser
)发起http请求→web服务器(例如 Tomcat
)接收请求→调用其内部一个方法完成请求处理或转发动作→将请求响应的资源返回给客户端;对于forward,转发的路径必须是同一个web容器下的URL,不能转向到另一个web路径上,转递的是request
,转发认为浏览器只做了一次访问请求redirect
行为:客户端发送http请求→web服务器接收后发送302状态响应码和对于的location给客户端→客户端检查响应头发现是302响应,则在次发送一次http请求,请求的是location中新的URL→服务器根据请求响应相应的资源返回客户端,由于是浏览器重新发起请求,那跟中间的request传递没有关系,重定位是客户端至少做了两次访问操作forward
:是将服务器内部将一个request
或response
的处理权限,交付给另一个Servlet
redirect
:是客户端request A,服务器响应,并response回来,告诉浏览器你应该去B,重定向可以访问自己web应用以外的资源redirect
(重定向):跳转后必须加上return
要不然页面虽然跳转了但是还会执行跳转后面的语句forward
(转发):是执行了跳转页面下面的代码就不会在执行了