request对象
一、request对象的各种api
@WebServlet("/request")
public class RequestServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求体
String method = request.getMethod(); //获取请求方法
String requestURL = request.getRequestURL().toString(); //获取URL
String requestURI = request.getRequestURI(); //获取URI
String protocol = request.getProtocol(); //获取协议类型及版本
System.out.println(method + " " + requestURI + " " + protocol);
System.out.println(method + " " + requestURL + " " + protocol);
System.out.println("---------------------------------");
//获取请求头
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()){
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
System.out.println(headerName + ":" + headerValue);
}
System.out.println("---------------------------------");
//获取地址及端口号
String remoteAddr = request.getRemoteAddr(); //获取客户端地址
int remotePort = request.getRemotePort(); //获取客户端端口号
String localAddr = request.getLocalAddr(); //获取服务器地址
int localPort = request.getLocalPort(); //获取服务器端口号
System.out.println(remoteAddr);
System.out.println(remotePort);
System.out.println(localAddr);
System.out.println(localPort);
}
}
输出结果:
GET /app2/request HTTP/1.1
GET http://localhost/app2/request HTTP/1.1
---------------------------------
host:localhost
connection:keep-alive
cache-control:max-age=0
upgrade-insecure-requests:1
user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36 SLBrowser/7.0.0.1071 SLBChan/25
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
sec-fetch-site:none
sec-fetch-mode:navigate
sec-fetch-user:?1
sec-fetch-dest:document
accept-encoding:gzip, deflate, br
accept-language:zh-CN,zh;q=0.9
cookie:JSESSIONID=085E5042592ACB4654BEC2BE52AF4DE6
---------------------------------
0:0:0:0:0:0:0:1
64172
0:0:0:0:0:0:0:1
80
二、获取form表单的参数
假如现在通过如下form表单来访问服务器:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/app2/submit2" method="post">
<input type="text" name="username"><br>
<input type="password" name="password"><br>
<input type="radio" name="gender" value="male">男
<input type="radio" name="gender" value="female">女<br>
<input type="checkbox" name="hobby" value="java">java
<input type="checkbox" name="hobby" value="python">python
<input type="checkbox" name="hobby" value="c++">c++<br>
<select name="province">
<option value="wuhan">武汉</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
</select>
<input type="submit">
</form>
</body>
</html>
用如下方法获取所有提交上来的属性:
@WebServlet("/submit")
public class SubmitServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Enumeration<String> parameterNames = req.getParameterNames();
while (parameterNames.hasMoreElements()){
String name = parameterNames.nextElement();
String[] parameterValues = req.getParameterValues(name);
System.out.println(name + ":" + Arrays.toString(parameterValues));
}
}
}
输出结果为:
username:[Octavius]
password:[123456]
gender:[male]
hobby:[java, python]
province:[wuhan]
三、封装数据
一般使用第三个工具类来封装数据,比如benautils类。
步骤:在开发目录中新建一个lib目录,然后导入下载的jar包,然后add as library。把jar包部署到应用的WEB-INF/lib目录下。
原因:Tomcat调用servlet时会先去应用的WEB-INF/classes目录下加载class文件,然后去应用的WEB-INF/lib目录下去加载所依赖的jar包。
封装代码如下
@WebServlet("/request2")
public class RequestServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求参数的map
Map<String, String[]> map = request.getParameterMap();
//创建要封装进去的user对象
User user = new User();
//利用beanutils将这些参数封装进对象
try {
BeanUtils.populate(user, map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println(user);
}
}
四、中文乱码问题
使用api:
void setCharacterEncoding(java.lang.String env)
throws java.io.UnsupportedEncodingException
在响应头上调用setCharacterEncoding(“编码格式”)方法,意思是将请求报文请求体的编码格式改成括号中的编码格式。
五、转发
思想:每一个模块只负责一个功能点,每个模块功能尽可能单一,那么它的复用性就越好。因此有时候一个请求需要多个servlet共同来处理
使用**getRequestDispatcher()**来转发
路径有三种写法
- 全路径(此处不可行)
request.getRequestDispatcher("http://localhost/app2/request3");
- 相对路径
request.getRequestDispatcher("request3");
- 应用名/资源名
request.getRequestDispatcher("app2/request3");
六、request域
Context域:能拿到一个context对象,这个context对象里都是键值对。
Context域的作用范围:整个应用,同一应用的任一servlet都能拿到这个context对象。
Request域:能拿到一个request对象,这个request对象里都是键值对。
Request域的作用范围:是转发包含中的源组件和目标组件。
共享域的条件:
context域,只要拿到的是同一个context对象,那么就可以共享同一个context域
request域,只要拿到的是同一个request对象,那么就可以共享同一个request域
@WebServlet("/domain1")
public class DomainServlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//request域
request.setAttribute("name", "zhangsan");
RequestDispatcher dispacher = request.getRequestDispatcher("domain2");
dispacher.forward(request, response);
}
}
@WebServlet("/domain2")
public class DomainServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = (String) request.getAttribute("name");
System.out.println(name);
}
}
response对象
一、response对象的各种api
@WebServlet("/response1")
public class ResponseServlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应状态码
response.setStatus(404);
//设置响应头
response.setHeader("Content-Type", "text/html");
response.setHeader("Server", "Tomcat 8.5");
//设置响应体
response.getWriter().println(new Date());
response.getWriter().println("<h1 style='color:red'>File Not Found</h1>");
}
}
二、中文乱码
有时候response.getWrite().print("中文")
这句话会在浏览器上显示为乱码
解决这个问题,我们不仅要设置响应体的编码格式,还要告诉浏览器我们的编码格式
一般有三种解决方案:
- 方案一
先设置响应体的编码格式
再写html格式的代码
@WebServlet("/char")
public class CharacterServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("utf-8");
//将浏览器的解码格式设置为utf-8
response.getWriter().println("<!DOCTYPE html>\n" +
"<html lang=\"en\">\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>Title</title>\n" +
"</head>\n" +
"<body>");
//前后是html页面的标准格式,中间写数据
response.getWriter().println("中国");
response.getWriter().println("</body>\n" +
"</html>");
}
}
- 方案二
设置响应头
Response.setHeader(“content-type”,”text/html;charset=utf-8”)
- 方案三
设置ContentType
response.setContentType("text/html;charset=utf-8");
三、输出字节数据
输出字节数据最常见的使用场景是去处理文件,去响应文件资源、二进制文件资源
比如:将本地部署根目录的下的1.jpg文件输出到客户端
思路:
- 先拿到文件的绝对路径
- 利用绝对路径,创造文件输入流,将文件的内容读取到输入流中
- 在response对象上调用
getOutputStream()
方法可以获得一个类似于文件输出流的输出流,他可以自动将流中的信息写到浏览器页面
@WebServlet("/stream")
public class OutputStreamServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("image/jpg");
ServletOutputStream outputStream = response.getOutputStream();
//1.先拿到文件的绝对路径
String realPath = getServletContext().getRealPath("1.jpg");
//2.创建输入流
FileInputStream fileInputStream = new FileInputStream(realPath);
int length = 0;
byte[] bytes = new byte[1024];
//3.创建输出流
ServletOutputStream outputStream = response.getOutputStream();
while ((length = fileInputStream.read(bytes)) != -1){
outputStream.write(bytes, 0, length);
}
fileInputStream.close();
//输出流可以关闭,也可以不关闭,如果不关闭,那么tomcat会在响应的时候帮你关闭
outputStream.flush();
outputStream.close();
}
}
设计缺省Servlet的原理与这个代码类似
四、定时刷新
- 方式一
//表示每隔2秒刷新一次页面
response.getWriter().print(new Date());
response.setHeader("refresh", "2");
- 方式二
//表示2秒过后,会跳转到指定url
response.setHeader("refresh", "2;url=test");
response.setHeader("refresh","2;url=" + request.getContextPath() + "/stream");
response.setHeader("refresh","2;url=http://www.baidu.com");
getContextPath()
方法是获取应用名
getServletPath()
方法是获取资源名
五、重定向
访问某一个地址,服务器返回一个302或者307的状态码,表示需要重定向,响应头还包含一个Location头,指明了下次重定向的路径。
- 方式一
response.setStatus(302)
response.setHeader("Location", request.getContextPath() + "/test")
- 方式二
response.sendRedirect(request.getContextPath() + "/test")