Java web 请求响应
本节主要普及一些概念性的知识,相比前两节操作较少,多多了解
一、Servlet 请求
1.获取路径
具体请求结果可以自己尝试
// 获取虚拟目录路径
public String getContextPath()
// 获取Servlet的映射路径
public String getServletPath()
// 获取访问者的ip地址
public String getRemoteAddr()
// 获取请求的消息数据
public String getQueryString()
// 获取统一资源标识符
public String getRequestURI()
// 获取统一资源定位符
public String getRequestURL()
2.获取请求头的信息
网址请求头:按f12打开开发者模式,然后进入一个网址,打开Notwork 点开一个请求,如图,headres里面就是请求头信息
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Iterator;
@WebServlet("/ServletRequest")
public class ServletRequest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取一个请求头
String connection = req.getHeader("connection");
System.out.println(connection);
System.out.println("================");
//获取一个请求的多个值,迭代器遍历
Enumeration<String> values = req.getHeaders("accept-encoding");
while (values.hasMoreElements()) {
String value = values.nextElement();
System.out.println(value);
}
System.out.println("================");
//获取说有的请求头名称,另外一种遍历方式
Enumeration<String> headerNames = req.getHeaderNames();
Iterator<String> stringIterator = headerNames.asIterator();
while (stringIterator.hasNext()) {
//通过请求头名称,根据名称获取值
String handName = stringIterator.next();
String handValue = req.getHeader(handName);
System.out.println(handName + " = "+ handValue);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
可以得到f12下说看到的,但是顺序不一定一致。
3.获取请求参数信息
// 根据参数名获取一个参数值
public String getParameter(String name)
// 根据参数名获取多个参数值
public String[] getParameterValues(String name)
// 获取所有的参数名称
public Enumeration<String> getParameterNames()
// 获取所有的参数名和参数值,并封装为Map集合
public Map<String,String[]> getParameterMap();
用来获取请求参数的值,可以编写一个html页面,跳转到Servlet 也可以直接通过地址栏来获取到值
我们在web目录下面新建regist.html页面并让他跳转到Servlet (此时我的虚拟路径名称为:demo01_war_exploded 所以在前面加上虚拟路径)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册</title>
</head>
<body>
<form action="/demo01_war_exploded/ServletRequestDemo02" method="post" autocomplete="off">
姓名:<input type="text" name="username" > <br>
密码:<input type="password" name="password"> <br>
爱好:<input type="checkbox" name="hobby" value="study" checked>学习
<input type="checkbox" name="hobby" value="book" checked>看书
<input type="checkbox" name="hobby" value="game" >游戏 <br>
<button type="submit">注册</button>
</form>
</body>
</html>
对应的Servlet
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
@WebServlet("/ServletRequestDemo02")
public class ServletRequestDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//根据参数名获取参数指
String username = req.getParameter("username");
System.out.println("姓名:"+username);
//根据参数名获取多个值
String[] hobbies = req.getParameterValues("hobby");
System.out.println("爱好:"+ Arrays.toString(hobbies));
System.out.println("---------");
//获取所有的参数名称
Enumeration<String> parameterNames = req.getParameterNames();
while (parameterNames.hasMoreElements()) {
String parameterName = parameterNames.nextElement();
String[] values = req.getParameterValues(parameterName);
System.out.println(parameterName+":"+Arrays.toString(values));
}
System.out.println("----------");
//获取所有的参数名和参数指,存入一个Map集合
Map<String, String[]> parameterMap = req.getParameterMap();
Set<String> keys = parameterMap.keySet();
for (String key : keys) {
String[] values = parameterMap.get(key);
System.out.println(key+"="+Arrays.toString(values));
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
访问如图路径并输入相应的值
点击注册按钮提交,在控制台得到结果
姓名:zhangsan
爱好:[study, book]
---------
username:[zhangsan]
password:[123456]
hobby:[study, book]
----------
username=[zhangsan]
password=[123456]
hobby=[study, book]
这样我们就能得到提交的数据,但是如果提交的值有很多,一次写一个的话未免太复杂了,所以我们可以 通过 beanutils工具类来封装请求结果
封装请求结果
首先新建一个类用来封装结果(对象名称必须和前台的name属性一致)
import java.util.Arrays;
public class Student {
private String username;
private String password;
private String[] hobby;
public Student() {
}
public Student(String username, String password, String[] hobby) {
this.username = username;
this.password = password;
this.hobby = hobby;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String[] getHobby() {
return hobby;
}
public void setHobby(String[] hobby) {
this.hobby = hobby;
}
@Override
public String toString() {
return "Student{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", hobby=" + Arrays.toString(hobby) +
'}';
}
}
然后再 web-> WEB-INF 下面新建一个lib包,将beanutils工具类的相关jar包导入,资源我会在结尾给出
接着来改造我们的Servlet,下面给出相关代码
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取所有的参数名和参数指,存入一个Map集合
Map<String, String[]> parameterMap = req.getParameterMap();
Student stu=new Student();
try {
BeanUtils.populate(stu,parameterMap);
System.out.println(stu);
} catch (Exception e) {
e.printStackTrace();
}
}
然后同样在前台提交,控制台得如下结果
Student{username='zhangsan', password='123', hobby=[study, book]}
注意:
- 我们封装类的对象的名称必须和前台name属性里的名称一致
- 导入包必须是在web -> WEB-> WEB-INF 下新建lib目录来存放jar包
- 如遇到中文乱码问题,在Servlet 加上 req.setCharacterEncoding(“utf-8”);来设置请求编码
二、Servlet响应
浏览器访问服务器后,服务器给客户端响应的数据会封装为ServletResponse对象,它有一个子类叫HttpServletResponse对象,用于封装按照Http协议封装的响应数据。
1.响应状态码
状态码 | 状态 |
---|---|
100 | 只有请求的一部分已经被服务器接收,但只要它没有被拒绝,客户端应继续该请求 |
200 | 请求成功 |
302 | 重定向,所请求的页面已经临时转移到一个新的 URL |
304 | 访问缓存,所请求的页面已经临时转移到一个新的 URL |
404 | 客户端错误,请求路径服务器没有对应的资源 |
405 | 客户端错误,请求方式找不到对应的方法 |
500 | 服务端错误,可能服务器内部有异常 |
2.解决响应乱码
注意:此方法虽然可以解决响应乱码,但是因为改变了响应方式为html,所以可能会造成css image 等资源无法访问
//设置响应编码,
resp.setContentType("text/html;charset=utf-8");
3.响应图片
在web/img目录下放一张a.jpeg图片,把图片中所有的字节响应给客户端。
@WebServlet("/ServletRequestDemo03")
public class ServletResponseDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取输出流对象
ServletOutputStream out = resp.getOutputStream();
//获取文件的绝对路径
String imgPath = getServletContext().getRealPath("img/a.jpeg");
//获取输入流对象
FileInputStream fis = new FileInputStream(imgPath);
byte[] bs=new byte[1024];
int len;
while ((len=fis.read(bs))!=-1){
out.write(bs,0,len);
}
fis.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
4.重定向和定时刷新
//定时刷新,3秒后跳转到指定页面
resp.setHeader("Refresh","3;url=regist.html");
//重定向
//重定向到regist.html
//resp.sendRedirect(req.getContextPath()+"//regist.html");
//也可以使用下面两个方法,完成重定向;302表示重定向的状态码
resp.setStatus(302);
resp.setHeader("location","regist.html");
//转发
req.getRequestDispatcher("regist.html").forward(req, resp);
注意:重定向和请求转发不太一样,请求转发是只有一个请求,而重定向有两次请求。所以重定向不能通过请求域共享数据,只有在同一个请求链中才能通过请求域中心数据。
5.文件下载
主要是这一句话,将资源以附件的形式接收
//设置响应头,告诉浏览器以附件形式接受
resp.setHeader("content-disposition","attachment;filename="+file.getName());
例如下载 img/a.jpg的图片
@WebServlet("/servletResponseDemo5")
public class ServletResponseDemo7 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//准备要下载的图片
File file=new File("img/a.jpg");
//设置响应头,告诉浏览器以附件形式接受
resp.setHeader("content-disposition","attachment;filename="+file.getName());
//获取输出流对象
ServletOutputStream out = resp.getOutputStream();
//获取文件的绝对路径
String imgPath = getServletContext().getRealPath(file.getPath());
//获取输入流对象
FileInputStream fis = new FileInputStream(imgPath);
byte[] bs=new byte[1024];
int len;
while ((len=fis.read(bs))!=-1){
out.write(bs,0,len);
}
fis.close();
}