如何将客户端发送的请求封装成Java中的一个对象?
HttpServletRequest类
客户端发送请求给Tomcat服务器的流程
-
Tomcat服务器会把请求封装到Request对象中
-
然后传递到service方法中(也就是HttpServlet中的
doGet
和doPost
方法中) -
通过这个HttpServletRequest对象获取所有的请求信息
HttpServletRequest类常用的方法
getRequestURL():获取请求的资源路径
getRequestURI():获取请求的统一资源定位符(绝对路径)
getRemoteHost():获取客户端的ip地址
getHeader():获取请求头
getParameter():获取请求的参数
getParameterValues():获取请求的参数数组
getMethod():获取请求的方式GET/POST
setAttribute(key,value):设置域数据
getAttribute(key):获取域数据
getRequestDispatcher():获取请求转发对象
请求转发流程
请求转发:由客户端发起请求给服务器,服务器从一个资源跳转到另一个资源的操作叫做请求转发
如下图:
请求转发的特征
-
浏览器地址不会发生任何变化
-
一次请求
-
共享Request域信息:因为forward将req和resp传递给了下一个Servlet资源
-
可以转发到WEB-INF目录下
//WEB-INF目录浏览器不允许访问,但是可以通过请求转发的方式进行访问 RequestDispatcher requestDispatcher = req.getRequestDispatcher("/WEB-INF/word.html"); requestDispatcher.forward(req, resp);
-
不可以访问工程以外的资源
测试代码req.setCharacterEncoding("UTF-8"); //获取请求参数 String username = req.getParameter("username"); //业务处理 System.out.println(username); req.setAttribute("李白", "是诗人"); //跳转到ForwardServlet页面 //WEB-INF目录浏览器不允许访问,但是可以通过请求转发的方式进行访问 RequestDispatcher requestDispatcher = req.getRequestDispatcher("/Forward"); requestDispatcher.forward(req, resp);
resp.setCharacterEncoding("UTF-8"); //获取请求参数 String username = req.getParameter("username"); //获取AcceptServlet的请求域参数--这样可以判断是否由AcceptServlet跳转过来的 Object attr = req.getAttribute("李白"); System.out.println(attr); //处理业务 resp.setContentType("text/html"); PrintWriter out = resp.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>Hello World</title>"); out.println("</head>"); out.println("<body>"); out.println("<form action="+"index.jsp"+">"); out.println("<input type="+"'submit' "+"value="+"'aaa'"+"/>"); out.println("</form>"); out.println("</body>"); out.println("</html>");
HTML中的base标签
base标签用于定义基础路径,基于base标签定义的路径进行跳转
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="html/base/1/base.html">跳转base.html</a>
<a href="http://localhost:8080/ServletWeb/Accept">请求转发</a>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试base的作用</title>
<!-- <base href="http://localhost:8080/ServletWeb/html/base/1/">-->
</head>
<body>
<a href="../../../index.jsp">a标签跳转index.jsp</a>
</body>
</html>
不使用base标签,相对路径中上一级是以浏览器链接路径为基础参照,而当使用请求跳转时不会改变浏览器的地址,因此…/…/无法返回上一级,出现如下图错误
使用base标签,以base标签中的href为基础参照,忽略浏览器路径,此时跳转正确
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试base的作用</title>
<base href="http://localhost:8080/ServletWeb/html/base/1/">
</head>
<body>
<a href="../../../index.jsp">a标签跳转index.jsp</a>
</body>
</html>
斜杠(/)的意义
被浏览器解析为http://localhost:8080
被服务器解析为当前工程下,即:http://localhost:8080/ServletWeb
在开发中使用绝对路径,避免使用相对路径,避免因项目迁移导致的路径错误,如果要使用相对路径,要使用base+相对路径
如何将服务器响应的信息封装成Java中的一个对象?
HttpServletResponse类
-
客户端发送请求给服务器,服务器需要对该请求进行响应
-
响应的内容需要程序员进行设置,就必须将该响应信息先封装为一个Java对象进行操作
-
然后通过流的方式传输到客户端
response中的两个输出流
字节流:getOutputStream(); 常用于下载二进制文件 字符流:getWriter(); 常用于回传字符串
Response响应并回传数据到浏览器常见乱码问题解决办法:
//解决乱码问题方法一:
//设置服务器编码字符集
resp.setCharacterEncoding("UTF-8");
//设置浏览器编码字符集
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
//解决乱码问题方法二:但是该方法一定要在获取流对象之前使用
resp.setContentType("text/html; charset=UTF-8");
响应重定向流程
请求重定向:是指客户端给服务器发送请求,服务器回传数据给客户端时,修改浏览器访问地址,重新定向到另一个资源点
流程如下:
请求重定向特点:
-
浏览器地址栏链接会发生变化
-
请求重定向为两次请求,第一次请求是用户键入的浏览器链接地址;第二次请求是服务器重定向地址
-
由于是两次请求,因此不共享Request域中的数据
-
请求重定向无法访问WEB-INF目录下的资源(原因:两次请求都是由客户端获取链接后发送的请求,浏览器请求无法访问WEB-INF目录下的资源,而请求转发是服务器获取WEB-INF目录下的资源后回传给客户端的)
-
可以访问工程外的资源,原理与第四点相似,浏览器自身根据链接发送请求,即使访问外网主机也可以(如:www.baidu.com)
-
请求重定向无论第一次访问资源是GET还是POST方法,重定向都默认是GET方法
302 Found
要求客户端执行临时重定向(原始描述短语为“Moved Temporarily”)。[20]由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。
新的临时性的URI应当在响应的Location域中返回。除非这是一个HEAD请求,否则响应的实体中应当包含指向新的URI的超链接及简短说明。
如果这不是一个GET或者HEAD请求,那么浏览器禁止自动进行重定向,除非得到用户的确认,因为请求的条件可能因此发生变化。
注意:虽然RFC 1945和RFC 2068规范不允许客户端在重定向时改变请求的方法,但是很多现存的浏览器将302响应视作为303响应,并且使用GET方式访问在Location中规定的URI,而无视原先请求的方法。因此状态码303和307被添加了进来,用以明确服务器期待客户端进行何种反应。
307 Temporary Redirect
在这种情况下,请求应该与另一个URI重复,但后续的请求应仍使用原始的URI。 与302相反,当重新发出原始请求时,不允许更改请求方法。 例如,应该使用另一个POST请求来重复POST请求
Tomcat默认是302
测试代码:
Response1
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// resp.setContentType("text/html;charset=UTF-8");
resp.setStatus(307);
System.out.println(resp.getStatus());
//方式1:使用设置响应头的方式设置Location参数
// resp.setHeader("Location","http://localhost:8080/ServletWeb/response2");
//方式2:
resp.sendRedirect("http://localhost:8080/ServletWeb/response2");
}
}
Response2
public class Response2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("这是Response2--GET");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("这是Response2--POST");
}
}