“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”
一、HttpServletRequest
每当有请求进入Tomcat,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到HttpServletRequest对象中,然后传递到service方法中,可以通过HttpServletRequest对象来获取客户端发来的请求中的信息
HttpServletRequest的常用方法
- getRequestURI(),获取请求的资源路径
- gerRequestURL(),获取请求的统一资源定位符
- getRemoteHost(),获取客户端IP
- getHeader(),获取请求头
- getParameter(),获取请求的参数
- getParameterValues(),获取请求中多个参数的值
- getMethod(),获取请求方式,GET或POST
- setAttribute(key,value),设置域数据
- getAttribute(key),获取域数据
- getRequestDispatcher(),获取请求转发对象
在controller包中增加HiServlet
代码语言:javascript复制public class HiServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取请求的资源路径
System.out.println("请求资源路径为:" req.getRequestURI());
// 2. 获取请求的URL地址
System.out.println("请求的URL地址为:" req.getRequestURL());
// 3. 获取请求的客户端IP地址
System.out.println("客户端IP地址为:" req.getRemoteHost());
// 4. 获取请求头
System.out.println("请求头为:" req.getHeader("User-Agent"));
// 5. 获取请求方式
System.out.println("请求方式为:" req.getMethod());
}
}
在web.xml中配置Servlet的访问路径
代码语言:javascript复制<servlet>
<servlet-name>HiServlet</servlet-name>
<servlet-class>com.lilith.servlet.HiServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HiServlet</servlet-name>
<url-pattern>/hi</url-pattern>
</servlet-mapping>
重启Tomcat,浏览器访问http://localhost:8080/hi
web目录下新增form.html页面,新增一个表单
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Form</title>
</head>
<body>
<form action="/param" method="get">
用户名:<input type="text" name="username"> <br>
密码: <input type="password" name="password"> <br>
兴趣爱好:<input type="checkbox" name="hobby" value="cpp"> C
<input type="checkbox" name="hobby" value="java"> Java
<input type="checkbox" name="hobby" value="python"> Python <br>
<input type="submit" value="提交">
</form>
</body>
</html>
新增ParamServlet类,用于获取表单提交的数据
代码语言:javascript复制public class ParamServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求中的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String hobby = req.getParameter("hobby");
System.out.println("请求中username参数的值为:" username);
System.out.println("请求中password参数的值为:" password);
System.out.println("请求中hobby参数的值为:" hobby);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
在web.xml中增加ParamServlet的访问配置
代码语言:javascript复制<servlet>
<servlet-name>ParamServlet</servlet-name>
<servlet-class>com.lilith.servlet.ParamServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ParamServlet</servlet-name>
<url-pattern>/param</url-pattern>
</servlet-mapping>
重启Tomcat,浏览器输入 http://localhost:8080/form.html, 在表单中输入数据后点击提交
当参数有多个值时,需要使用getParameterValues来获取,getParameter只能获取参数的第一个值
代码语言:javascript复制// 获取请求中的参数(有多个值)
String[] hobbies = req.getParameterValues("hobby");
System.out.println("请求中hobby参数的所有值:" Arrays.asList(hobbies));
中文乱码问题
表单中输入中文,点击提交
当请求方式为GET请求时,中文可以正常显示
更改form.html中请求方式为post,将goGet方法中的代码拷贝至doPost方法中,在表单中再次提交中文信息
代码语言:javascript复制@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost方法被调用!");
// 获取请求中的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String hobby = req.getParameter("hobby");
System.out.println("请求中username参数的值为:" username);
System.out.println("请求中password参数的值为:" password);
System.out.println("请求中hobby参数的值为:" hobby);
// 获取请求中的参数(有多个值)
String[] hobbies = req.getParameterValues("hobby");
System.out.println("请求中hobby参数的所有值:" Arrays.asList(hobbies));
}
根据控制台的输出,POST提方式提交时中文乱码了。
doPost方法中增加编码设置
代码语言:javascript复制req.setCharacterEncoding("UTF-8");
再次提交表单
中文乱码问题已解决
Servlet的请求转发
请求转发是指服务器收到请求后,从一个资源跳转到另一个资源的操作。
在controller包中新建两个Servlet类AlphaServlet和BravoServlet,用作实现请求转发
代码语言:javascript复制public class AlphaServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求参数
String username = req.getParameter("username");
System.out.println("alpha请求中参数username的值为:" username);
// 要转发到BravoServlet的地址
// 请求转发的地址必须要以/开头
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/bravo");
// 转发到BravoServlet
requestDispatcher.forward(req,resp);
}
}
代码语言:javascript复制public class BravoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
System.out.println("bravo请求中参数username的值为:" username);
System.out.println("BravoServlet业务处理");
}
}
在web.xml中配置AlphaServlet和BravoServlet的访问路径
代码语言:javascript复制<servlet>
<servlet-name>AlphaServlet</servlet-name>
<servlet-class>com.lilith.servlet.AlphaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AlphaServlet</servlet-name>
<url-pattern>/alpha</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>BravoServlet</servlet-name>
<servlet-class>com.lilith.servlet.BravoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BravoServlet</servlet-name>
<url-pattern>/barvo</url-pattern>
</servlet-mapping>
重新启动Tomcat,在浏览器中输入 http://localhost:8080/alpha?username=peter, 点击回车
F12打开浏览器的检查页面,查看网络可以确定从请求AlphaServlet然后转发到BravoServlet只发了一次请求,也就是说请求AlphaServlet和AlphaServlet转发到BravoServlet是同一个请求,所以在两个Servlet中都可以获取到username参数的值
并且浏览器的地址栏没有变化。
请求转发可以访问WEB-INF下的文件
在WEB-INF下新建success.html页面
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>SUCCESS</title>
</head>
<body>
<h1>成功转发到WEB-INF目录下</h1>
</body>
</html>
修改AlphaServlet,使其转发到success.html页面
代码语言:javascript复制RequestDispatcher requestDispatcher = req.getRequestDispatcher("/WEB-INF/success.html");
重新启动应用
浏览器输出了success页面的内容,转发可以访问WEB-INF下的文件
请求转发的特点
- 浏览器地址栏没有变化
- 是同一次请求
- 共享Request域中的数据
- 可以转发到WEB-INF目录下
- 不可以访问工程以外的资源
Web中的相对路径和绝对路径
在JavaWeb中,路径分为相对路径和绝对路径 相对路径
- .:表示当前目录
- ..:表示上一级目录
- 资源名:表示当前目录/资源 绝对路径
- http://ip:port/工程路径/资源路径
Web中 “/” 的不同意义
在Web中 “/” 是一种绝对路径
- “/” 如果被浏览器解析,得到的地址是:http://ip:port/
- “/” 如果被服务器解析,得到的地址是:http://ip:port/工程路径
- 重定向的地址为“/”时,发送给浏览器解析,地址是http://ip:port/
二、HttpServletResponse
HttpServletResponse和HttpServletRequest类一样,每次请求进来Tomcat都会创建一个Response对象传递给Servlet程序使用,HttpServletRequest表示请求传过来的信息,HttpServletResponse表示所有响应的信息;如果需要返回给客户端消息,可以使用HttpServletResponse对象来进行设置
HttpServletResponse使用输出流来给客户端发送消息
- 字节流,getOutputStream(); 常用于下载(传递二进制数据)
- 字符流,getWriter();常用与回传字符串(常用) 另个流只能同时使用一个。
在controller包中创建一个SteamServlet类,同时使用字符流和字节流
代码语言:javascript复制public class StreamServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter();
resp.getOutputStream();
}
}
在web.xml中配置Servlet的访问路径
代码语言:javascript复制<servlet>
<servlet-name>SteamServlet</servlet-name>
<servlet-class>com.lilith.servlet.StreamServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SteamServlet</servlet-name>
<url-pattern>/stream</url-pattern>
</servlet-mapping>
重启Tomcat,浏览器输入 http://localhost:8080/stream
页面出现报错
修改StreamServlet,只使用字符流
代码语言:javascript复制public class StreamServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
// resp.getOutputStream();
writer.write("Response Content");
}
}
重启Tomcat,浏览器输入 http://localhost:8080/stream
浏览器返回response信息
响应中文乱码问题解决方案一
设置StreamServlet中返回的内容是中文格式,并重启Tomcat,浏览器输入同一地址
页面输出的中文出现乱码现象
在代码中获取字符编码,重启Tomcat,访问同一地址
在代码中设置响应的编码格式
代码语言:javascript复制public class StreamServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置UTF-8编码
resp.setCharacterEncoding("UTF-8");
PrintWriter writer = resp.getWriter();
// resp.getOutputStream();
String characterEncoding = resp.getCharacterEncoding();
System.out.println("字符编码给为:" characterEncoding);
writer.write("这是响应内容");
}
}
重启Tomcat,访问/stream
还是出现乱码现象
应为还需要通过请求头设置浏览器字符集
代码语言:javascript复制public class StreamServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置UTF-8编码
resp.setCharacterEncoding("UTF-8");
// 响应头设置UTF-8字符集
resp.setHeader("Content-Type","text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
// resp.getOutputStream();
String characterEncoding = resp.getCharacterEncoding();
System.out.println("字符编码给为:" characterEncoding);
writer.write("这是响应内容");
}
}
重启Tomcat,访问/stream
中文可以正常显示
响应中文乱码问题解决方案二
代码语言:javascript复制@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置UTF-8编码
// resp.setCharacterEncoding("UTF-8");
// 响应头设置UTF-8字符集
// resp.setHeader("Content-Type","text/html;charset=UTF-8");
// 一句代码解决
resp.setContentType("text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
// resp.getOutputStream();
String characterEncoding = resp.getCharacterEncoding();
System.out.println("字符编码给为:" characterEncoding);
writer.write("这是响应内容");
}
使用resp.setContentType("text/html;charset=UTF-8") 可以同时设置服务器和客户端都是用UTF-8编码,同时设置了响应头,并且该方法一定要在获取流对象之前调用才会生效
重启Tomcat,再次访问/stream
请求重定向
请求重定向,指的是客户端发送给服务器请求后,服务端返回一个新的地址,客户端重新访问这个新的地址,称为请求的重定向。
在controller包中新建两个Servlet,用于实现请求的重定向
代码语言:javascript复制public class DeltaServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(this.getClass().getName());
resp.setStatus(302);
resp.setHeader("Location","http://localhost:8080/echo");
}
}
代码语言:javascript复制public class EchoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(this.getClass().getName());
resp.getWriter().write(this.getClass().getName());
}
}
在web.xml配置两个Servlet的访问路径
代码语言:javascript复制<servlet>
<servlet-name>DeltaServlet</servlet-name>
<servlet-class>com.lilith.servlet.DeltaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DeltaServlet</servlet-name>
<url-pattern>/delta</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>EchoServlet</servlet-name>
<servlet-class>com.lilith.servlet.EchoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EchoServlet</servlet-name>
<url-pattern>/echo</url-pattern>
</servlet-mapping>
重启Tomcat,并在浏览器中输入http://localhost:8080/delta
根据浏览器的显示的内容可以确定请求重定向的一些特点
- 请求重定向发生后浏览器地址栏会发生变化
- 请求重定向实际发生了两次请求
- 请求重定向不共享Request域中的数据
测试重定向是否能够跳转到WEB-INF下面的页面中
代码语言:javascript复制resp.setHeader("Location","http://localhost:8080/WEB-INF/success.html");
重新启动应用
访问失败,重定向不可以访问WEB-INF下的资源,但是重定向可以反问工程外的资源
请求重定向第二种实现方式(推荐使用)
代码语言:javascript复制resp.sendRedirect("http://localhost:8080/echo");
代替设置响应码和header
代码语言:javascript复制public class DeltaServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(this.getClass().getName());
// resp.setStatus(302);
// // resp.setHeader("Location","http://localhost:8080/echo");
// resp.setHeader("Location","http://localhost:8080/WEB-INF/success.html");
resp.sendRedirect("http://localhost:8080/echo");
}
}
重启应用,仍然可以实现重定向,推荐使用第二种方式