目录
Request体系结构
- ServletRequest:是一个接口
- HttpServletRequest:是一个接口
- org.apache.catalina.connector.RequestFacade:是 Tomcat 的一个类
RequestFacade 类实现了 HttpServletRequest 接口,HttpServletRequest 接口继承了 ServletRequest 接口
HttpServletRequest常用方法
ServletRequest接口:
请求对象, 封装了获取所有请求信息(请求行, 请求头, 请求实体)的方法HttpServletRequest接口:
是ServletRequest的子接口, 处理HTTP协议请求的方法.
常用方法
- String getMethod(): 返回请求方式(GET/POST)
- String getRequestURI():返回请求行中资源名字部分: 如/test/index.html
- StringBuffer getRequestURL():返回浏览器地址栏的内容
- String getContextPath():获取上下文路径(虚拟目录),<Context path=“上下文” …/>
- String getRemoteAddr():返回请求服务器的客户端的IP地址
- String getHeader(String headName):根据指定的请求头获取对应的请求头的值.
获取请求参数的方法
- String getParameter(String name):根据参数名称,获取对应参数的值.
- String[] getParameterValues(String name):根据参数名称,获取该参数的多个值.
- Enumeration<String> getParameterNames(): 获取所有请求参数的名字
- Map<String,String[]> getParameterMap():返回请求参数组成的Map集合.
key:参数名称
value:参数值,封装在String数组中.
注意:
- String getInitParameter(String name): 获取初始化参数, 初始化参数是开发人员设置
- String getParameter(String name): 获取用户输入的参数, 参数是不同用户输入的(通过表单)
// 注解: 表示Web.xml中给这个Servlet配置的8句
@WebServlet("/req")
public class HttpServletRequestDemo extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//- String getMethod(): 返回请求方式(GET/POST)
System.out.println(req.getMethod());
//- String getRequestURI():返回请求行中资源名字部分: 如/test/index.html
System.out.println(req.getRequestURI());
//- StringBuffer getRequestURL():返回浏览器地址栏的内容
System.out.println(req.getRequestURL());
//- String getContextPath():获取上下文路径,<Context path="上下文" ../>
System.out.println(req.getContextPath());
//- String getRemoteAddr():返回请求服务器的客户端的IP地址
System.out.println(req.getRemoteAddr());
//- String getHeader(String headName):根据指定的请求头获取对应的请求头的值.
String userAgent = req.getHeader("User-Agent");
System.out.println(userAgent.contains("MSIE"));
System.out.println(userAgent);
System.out.println("-----------获取请求参数的方法----------");
// String getParameter(String name):根据参数名称,获取对应参数的值.
System.out.println(req.getParameter("username"));
// String[] getParameterValues(String name):根据参数名称,获取该参数的多个值.
String[] hobbies = req.getParameterValues("hobby");
System.out.println(Arrays.toString(hobbies));
// Enumeration<String> getParameterNames():获取所有请求参数的名字
Enumeration<String> parameterNames = req.getParameterNames();
while (parameterNames.hasMoreElements()) {
System.out.println("====>" + parameterNames.nextElement());
}
// Map<String,String[]> getParameterMap():返回请求参数组成的Map集合.
Map<String, String[]> parameterMap = req.getParameterMap();
System.out.println(parameterMap);
}
}
请求转发
跳转到目录
一种在服务器内部的资源跳转方式
-
通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
-
使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
-
特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器内部资源中
- 转发只发送一次请求
-
RequestSkipDemo.java
@WebServlet("/skip") public class RequestSkipDemo extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("ServletSkipDemo~~~"); // 转发到skip2资源 req.getRequestDispatcher("/skip2").forward(req, resp); } }
-
RequestSkipDemo1.java
@WebServlet("/skip2") public class RequestSkipDemo1 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("skip2"); } }
共享数据
跳转到目录
- 域对象: 一个有作用范围的对象,可以在范围内共享数据
- request域: 代表一次请求的范围,一般用于请求转发的多个资源中共享数据
- 方法
- void setAttribute(String name,Object obj):存储数据
- Object getAttitude(String name):通过键获取值
- void removeAttribute(String name):通过键移除键值对
注册案例
-
通过RegisterServlet来获取注册界面传送过来的参数.
-
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册界面</title>
</head>
<body>
<h3>注册界面</h3>
<form action="/register/reg" method="post">
账号:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
性别:
<input type="radio" name="gender" value="boy" checked>男
<input type="radio" name="gender" value="girl">女<br>
爱好:
<input type="checkbox" name="hobby" value="Java" checked>java
<input type="checkbox" name="hobby" value="C" checked>C
<input type="checkbox" name="hobby" value="Swift" checked>Swift<br>
城市:
<select name="city">
<option value="ny">南阳</option>
<option value="tb">桐柏</option>
<option value="bj">北京</option>
</select><br>
自我介绍:<textarea rows="5" cols="15" name="intro"></textarea><br>
<input type="submit" value="注册">
</form>
</body>
</html>
- RegisterServlet.java
@WebServlet("/reg")
public class RegisterServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
String gender = req.getParameter("gender");
String city = req.getParameter("city");
String intro = req.getParameter("intro");
String[] hobbies = req.getParameterValues("hobby");
System.out.println(username);
System.out.println(password);
System.out.println(gender);
System.out.println(city);
System.out.println(intro);
System.out.println(Arrays.toString(hobbies));
}
}
请求的中文乱码处理
- 在Tomcat中, 对于POST和GET请求,默认是
ISO-8859-1
的编码格式, 而该编码格式不支持中文, 所以会产生乱码. - 解决方案 :
第一种方式:
- 对乱码使用ISO-8859-1解码—>byte数组.
- 对byte数组重新使用UTF-8编码
String username1 = req.getParameter("username"); // 按照ISO-8859-1把乱码恢复成二进制形式 byte[] data = username1.getBytes("ISO-8859-1"); // 再把二进制形式的数据使用UTF-8重新编码 String username2 = new String(data, "UTF-8"); System.out.println(username2);
问题: 这种方式当一个参数需要使用这两行代码来转码,如果有N个中文参数,就需要写N次,如此一来, 冗余代码很多.
第二种方式:
- 针对POST请求方式
req.setCharacterEncoding("UTF-8");
// 对于POST请求 可以设置请求的编码 req.setCharacterEncoding("UTF-8"); String username = req.getParameter("username"); System.out.println(username);
注意:
这种方式只对POST有效, 必须放在获取任意参数之前 - 针对GET请求方式(了解)
这种方式只对GET有用.
HttpServletResponse常用方法
ServletResponse接口:
响应对象, 封装了获取所有响应信息(状态行, 响应头, 请求实体)的方法HttpServletResponse接口:
是ServletResponse的子接口, 处理HTTP协议响应的方法.
常用方法
- OutputStream getOutputStream():获取字节输出流对象. :文件下载
- Writer getWriter():获取字符输出流对象 :输出内容
// 演示HttpServletResponse
@WebServlet("/resp")
public class HttpServletResponseDemo extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 在浏览器中输出Hello_ZYGui
// ServletOutputStream out = resp.getOutputStream();
// out.write("Hello_ZYGui桂朝阳".getBytes());
// 使用字符输出流,中文会出现乱码,需要设置两行代码
// 设置输出数据的MIME类型
// resp.setContentType("text/html");
// 设置输出数据的编码方式
// resp.setCharacterEncoding("UTF-8");
// 这两行可以统一设置
resp.setContentType("text/html;character=utf-8");
PrintWriter out1 = resp.getWriter();
out1.println("Hello_桂朝阳"); // 输出到浏览器上
}
}
重定向
- 重定向是一种资源跳转的方式
- 实现方式
//当访问responseDemo1,会自动跳转到/responseDemo2 // ---------方式一------------ // 设置状态码 // resp.setStatus(302); // 设置响应头 location // resp.setHeader("location", "/ZYServlet/responseDemo2"); // ---------方式二------------ resp.sendRedirect("/ZYServlet/responseDemo2");
-
重定向的特点:redirect
1. 地址栏发生变化
2. 重定向可以访问其他站点(服务器)的资源
3. 重定向是两次请求。不能使用request对象来共享数据 -
转发的特点:forward
1. 转发地址栏路径不变
2. 转发只能访问当前服务器下的资源
3. 转发是一次请求,可以使用request对象来共享数据 -
路径写法:
- 相对路径:通过相对路径不可以确定唯一资源
* 如:./index.html
* 不以/开头,以.开头路径
规则:找到当前资源和目标资源之间的相对位置关系
* ./:当前目录
* …/:后退一级目录
2. 绝对路径:通过绝对路径可以确定唯一资源
* 如:http://localhost/day15/responseDemo2
/day15/responseDemo2
* 以/开头的路径
规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
* 建议虚拟目录动态获取:request.getContextPath()
* <a> , <form> 重定向…
* 给服务器使用:不需要加虚拟目录
* 转发路径