web02_request_response
第一章 servletContext对象
1.什么是ServletContext
在Tomcat服务器中的web项目也叫作web应用程序。在java中万物皆对象,那么,应用程序也是对象
在java web开发中,使用ServletContext对象表示web应用程序
说明:
- 在web应用程序中,只能存在一个servletcontext对象
- 每个应用程序,都有自己所对应的一个ServletContext对象。
- 在服务器启动的时候,为每个web应用程序创建一个单独的ServletContext对象
- ServletContext是接口,此接口的实现类是Tomcat引擎提供的
2.ServletContext对象的作用
- 获取WEB应用程序的初始化参数
- 获取WEB应用程序下任意资源的绝对路径
- ServletContext作为域对象,存储数据
3.如何获取ServletContext对象
一个web应用程序只有一个ServletContext对象
1.通过ServletConfig接口获取
通过ServletConfig接口获取,他提供了方法getServletContext()
public interface servletconfig{
ServletContext getServletContext();
}
2.通过继承
通过继承的HttpServlet类的父类GenericServlet获取, GenericServlet类 提供了方法 getServletContext(),下面是源码分析
class Context1Servlet extends HttpServlet {}
↓
↓
public abstract class HttpServlet extends GenericServlet{}
↓
↓
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
//用transient关键字标记的成员变量不参与序列化过程。
private transient ServletConfig config;
public ServletConfig getServletConfig() {
return this.config;
}
public ServletContext getServletContext() {
return this.getServletConfig().getServletContext();
}
//省略其他
}
代码演示
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//方式1:通过ServletConfig对象获取,它提供了方法 getServletContext()
ServletConfig config = super.getServletConfig();
ServletContext servletContext = config.getServletContext();
System.out.println("servletContext = "+servletContext);
//方式2:通过继承的HttpServlet类的父类GenericServlet获取, GenericServlet类 提供了方法 getServletContext()
ServletContext servletContext2 = super.getServletContext();
System.out.println("servletContext2 = "+servletContext2);
}
4.作用一:获取WEB应用程序的初始化参数
因为一个web应用程序只有一个ServletContext对象,所以这个对象对整个应用程序的相关内容都是了解的
- web.xml 配置WEB应用程序的初始化参数
<!-- 配置的是WEB程序的初始化参数-->
<context-param>
<param-name>heima</param-name>
<param-value>java</param-value>
</context-param>
- API操作
方法 | 返回值 | 描述 |
---|---|---|
getInitParameter(String name) | String | 获取web应用程序的初始化参数 |
- 代码演示:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* 获取ServletContext对象
* 父类的方法
* org.apache.catalina.core.ApplicationContextFacade实现接口ServletContext
*/
ServletContext context = getServletContext();
System.out.println(context);
//context对象,获取配置文件中的初始化参数
String value = context.getInitParameter("heima");
System.out.println(value);
}
5.作用二:获取WEB应用程序下任意资源的绝对路径
方法 | 返回值 | 描述 |
---|---|---|
getRealPath(String path) | String | 接收一个资源的相对路径,返回真实路径(完整路径)的字符串 |
- 获取web目录下的a.txt绝对路径
- 获取web目下WEB-INF目录下的b.txt绝对路径
- 获取src目录下的c.txt绝对路径
- 获取web02 module下的d.txt绝对路径,获取不到
代码演示:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取servletContext对象
ServletContext servletContext = super.getServletContext();
//获取web目录下的a.txt绝对路径
String apath = servletContext.getRealPath("a.txt");
System.out.println("apath = " + apath);
//获取web目录下WEB-INF目录下的b.txt绝对路径
String bpath = servletContext.getRealPath("WEB-INF/b.txt");
System.out.println("bpath = " + bpath);
//获取src目录下的c.txt绝对路径
String cpath = servletContext.getRealPath("WEB-INF/classes/c.txt");
System.out.println("cpath = " + cpath);
}
6.作用三:ServletContext作为域对象
ServletContext作为域对象
ServletContext是在服务器启动的时候为每个web项目 单独创建一个ServletContext对象。当web项目从服务器中移除,或者是关闭服务器的时候ServletContext对象会被销毁。向ServletContext中保存的数据一直存在(当服务器关闭的时候ServletContext对象被销毁,然后里面数据才会失效)。
- ServletContext作用范围:整个web应用。
方法 | 返回值 | 描述 |
---|---|---|
setAttribute(String key, Object value) | void | 向域对象存储数据 |
getAttribute(String key) | Object | 取出域对象数据 |
removeAttribute(String key) | void | 移除域对象数据 |
代码演示:
第一个Servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取servletcontext对象
ServletContext context = super.getServletContext();
//存储数据 heima=java
context.setAttribute("heima","java");
//读取数据 heima的值
Object value = context.getAttribute("heima");
System.out.println("Context4Servlet heima = " + value);
}
第二个Servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletContext域对象
ServletContext context = super.getServletContext();
//获取域对象中 指定键的值
Object value = context.getAttribute("heima");
System.out.println("Context5Servlet heima = " + value);
}
第二章 Response对象
1.概述
方向:服务器 --> 浏览器 适用于任何网络传输协议
负责对浏览器进行响应的对象
响应:服务器接收到请求需要进行处理,将处理以后的结果现实会浏览器端。将这个过程称之为响应Response。
- 查看Servlet中的service方 法得知, Servlet中使用的ServletResponse接口, 而我们使用的是ServletResponse的子接口HttpServletResponse, 它继承自ServletResponse, 是与HTTP协议相关的Response响应对象
- 我们使用的子接口HttpServletResponse, 此接口对象由Tomcat引擎提供
- 可以实现对客户端的响应
- 相应内容包括
- 响应行:协议名 状态码
- 响应头:键值对格式 数据k:v的形式
- 响应体:页面正文,浏览器显示
- 相应内容包括
2.Response设置响应行
方法 | 返回值 | 描述 |
---|---|---|
setStatus(int sc) | void | 设置响应的状态码 |
- 设置响应的状态码
- 200 正确
- 302 重定向
- 304 查找本地缓存
- 404 请求资源不存在
- 500 服务器内部错误
response.setStatus(500);
3.Response设置响应头
HTTP协议的响应头,数据格式键值对 k:v
包含指导性信息,指导客户端
方法 | 返回值 | 描述 |
---|---|---|
addHeader(String key,String value) | void | 添加响应头,值为String类型 |
addIntHeader(String key,int value) | void | 添加响应头,值为int类型 |
addDateHeader(String key,long l) | void | 添加响应头,值为日期类型 |
setHeader(String key,String value) | void | 更改响应头,值为String类型 |
setIntHeader(String key,int value) | void | 更改响应头,值为int类型 |
setDateHeader(String key,long l) | void | 更改响应头,值为日期类型 |
-
add开头的方法:针对一个key对应多个value的情况。
比如已有一个响应头 heima:java 然后执行 addHeader(“heima”,”java2222”); 最终得到响应头的结果:heima:java,java2222
-
set开头的方法:针对一个key对应一个value的情况。
比如已有一个响应头 heima:java 然后执行 setHeader(“heima”,”java2222”); 最终得到响应头的结果:heima:java2222
演示:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* response对象设置响应头
*/
response.addHeader("heima","java");
/* response.addIntHeader("heima2",5);
response.addDateHeader("date",System.currentTimeMillis());*/
/*
* addHeader() 添加,实现一个键对应多个值
* setHeader() 设置,原来的键覆盖
*/
response.setHeader("heima","java2222");
}
4.重定向
4.1 重定向的写法
浏览器进行重新的定向:
- 设置302状态码: setStatus(302)
- 设置重定向资源的地址: setHeader("location","资源")
通过HttpServletResponse对象中的以下方法实现重定向
方法 | 返回值 | 描述 |
---|---|---|
sendRedirect(String location) | void | 重定向 |
4.2 重定向的代码实现
package cn.itcast.web;
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;
@WebServlet("/demo07")
public class ServletDemo07 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 解决服务器给浏览器的数据中文乱码问题
response.setContentType("text/html;charset=utf-8");
System.out.println("77777777777777777777777");
// 需求: 演示重定向: 访问 demo07 跳转到 demo08
// 方式一: 分解式
// 1 设置状态码 为 302 , 通知浏览器访问新资源
// response.setStatus(302);
// 2 设置响应头 location, 通知浏览器访问新资源的路径
// 新资源的路径 可以使 项目内的资源,也可以是项目外的资源
// response.setHeader("location", "/web0201/demo08");
// 方式二: 合并式
response.sendRedirect("/web0201/demo08");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
5 Response设置响应体
HTTP的响应体,就是页面的正文部分
5.1 字符流向浏览器写数据
方法 | 返回值 | 描述 |
---|---|---|
write() | PrintWriter | 使用字符串数据,没有差别, 输出是整数,查询编码表 |
print() | PrintWriter | 无论是什么,原样打印 |
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* response对象方法getWriter()
* 打印流的响应体
* write() 使用字符串数据,没有差别, 输出是整数,查询编码表
* print() 无论是什么,原样打印
*/
PrintWriter pw = response.getWriter();
pw.write(100);
pw.print(100);
}
5.2 字符流的中文乱码问题
产生乱码原因: 编码和解码不一致
提问:在Servlet中编写以下代码,向页面输出中文是否会产生乱码?
response.getWriter().print("中文");
会乱码:
- 原因:
- 字符流是有缓冲区的,response获得字符流,response设计默认的缓冲区编码是ISO-8859-1。这个字符集不支持中文的。
- 解决:
- 设置response获得字符流缓冲区的编码 与 设置浏览器默认打开时候采用的字符集一致即可。
方法 | 放回值 | 描述 |
---|---|---|
setHeader("Content-Type", "text/html;charset=UTF-8") | void | 设置浏览器打开页面时采用的字符集 |
setContextType(String type) | void | 设置浏览器打开页面时采用的字符集 |
// 设置浏览器默认打开的时候采用的字符集:
// response.setHeader("Content-Type", "text/html;charset=UTF-8");
// 简化代码
response.setContentType("text/html;charset=UTF-8");
// 输出中文汉字
response.getWriter().println("中文");
小结
浏览器发送过来中文数据,如果服务端接收乱码,使用request设置
服务端发送给客户端的中文数据,浏览器显示乱码,使用response设置
服务器输出到浏览器乱码
方法一:
数据写在response对象缓冲区,设置流的默认编码:IOS-8859-1
所以获取流对象之前,
修改response的编码表为utf-8
response.setCharacterEncoding("utf-8");
告知浏览器用utf-8解码
response。getWriter().write(" ");
方法二:
或者直接设置
response.setContentType("text/html;charset=utf-8");
解决服务器输出到浏览器中文乱码
5.3 字节流向浏览器写数据
方法 | 返回值 | 描述 |
---|---|---|
getOutputStream() | OutputStream | 返回字节输出流OutputStream,响应非文本类型的数据 |
5.3.1 案例 验证码
验证码的本质是个图片,图片里面是个随机生成字符串
随机字符串的思想:
String str ="abcdefABCDE1234567890";
Random.nextInt( str.length() )产生整数随机数
str.charAt(索引)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function changeImg(){
// 1 获取验证码图片对象
var codeImgObj = document.getElementById("codeImg");
// 2 修改图片的路径
// ?key=val 目的: 欺骗浏览器这是一个新资源
codeImgObj.src = "/web0202/demo11?r=" + Math.random();
}
</script>
</head>
<body>
<form action="xx" method="post">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="username"/></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password"/></td>
</tr>
<tr>
<td>验证码</td>
<td>
<input type="text" name="code_form"/>
<img src="/web0202/demo11" onclick="changeImg()" id="codeImg"/>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"/></td>
</tr>
</table>
</form>
</body>
</html>
package cn.itcast.web;
import javax.imageio.ImageIO;
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.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet("/demo11")
public class ServletDemo11 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 解决服务器给浏览器的数据中文乱码问题
// response.setContentType("text/html;charset=utf-8");
// 1 创建画布对象
int width = 120;
int height = 40;
BufferedImage bufi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 3 获取画笔
Graphics g = bufi.getGraphics();
// 4 修改背景色
g.fillRect(0, 0, width, height);
// 5 绘制边框
g.setColor(Color.red);
g.drawRect(0, 0, width-1, height-1);
// 6 生成随机字符 且 显示
// 6.1 准备数据
String data = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz123456789";
// 6.2 创建随机对象
Random r = new Random();
// 7.1 准备变量保存 生成的 随机字符
String code = "";
// 6.3 循环输出
for (int i = 0; i < 4; i++) {
// 6.3.2 设置字体
g.setFont(new Font("楷体", Font.BOLD, 30));
// 6.3.3 设置随机颜色
g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
// 6.3.1 绘制字符
char c = data.charAt(r.nextInt(data.length()));
g.drawString(c + "", 10 + i * 30, 30);
// 7.1 将生成的随机字符 保存到 随机字符串中
code += c +"";
}
// 7 将生成的字符输出到控制台
System.out.println(code);
// 8 绘制干扰线
for (int i = 0; i < 10; i++) {
// 8.2 设置随机颜色
g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
// 8.1 绘制干扰线
g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
}
// 2 将画布输出到浏览器中
ImageIO.write(bufi, "jpg", response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
第三章 Request对象
1 Request对象概述
方向: 浏览器 -> 服务器
负责获取客户端的请求数据
request对象是从客户端向服务器发出请求,包括用户提交的信息以及客户端的一些信息。客户端可通过HTML表单或在网页地址后面提供参数的方法提交数据,然后服务器通过request对象的相关方法来获取这些数据。
-
查看Servlet中的service方法得知, Servlet中使用的ServletRequest接口, 而我们使用的是ServletRequest的子接口HttpServletRequest, 它继承自ServletRequest, 是与HTTP协议相关的Request请求对象
-
我们使用的子接口HttpServletRequest, 此接口对象由Tomcat引擎提供
-
可以实现客户端向服务器发出请求, 请求内容包括: 请求行,请求头,请求体
2 Request对象获取请求行
- API
方法 | 返回值 | 描述 |
---|---|---|
getMethod() | String | 获取提交的方式 (GET,POST) |
getRequestURI() | String | 获取请求的参数,请求服务器路径 |
getRequestURL() | StringBuffer | 获取请求的参数,请求服务器路径 |
getQueryString() | String | 获取请求行 问号后面的参数 (GET) |
getContextPath() | String | 获取WEB应用名称 |
- 代码演示
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//request对象方法 getMethod()获取客户端的请求方式
String method = request.getMethod();
System.out.println(method);
//方法 String getRequestURI() 获取请求服务器路径
//方法 StringBuffer getRequestURL() 获取请求服务器路径
String URI = request.getRequestURI();
StringBuffer URL = request.getRequestURL();
System.out.println("URI=="+URI);// /web04/line
System.out.println("URL=="+URL);// http://localhost:8080/web04/line
//方法 String getQueryString()获取请求行,?后面的所有参数
String query = request.getQueryString();
System.out.println(query);//user=tom&pass=123&
//获取WEB应用名称 String getContextPath()
String path = request.getContextPath();
System.out.println(path);// /web04
//获取WEB应用名称, 结合重定向使用
//response.sendRedirect(request.getContextPath()+"/ddd");
}
3 Request对象获取请求头
请求头数据格式键值对, k:v
指导性信息,指导服务器
方法 | 返回值 | 描述 |
---|---|---|
getHeader(String name) | String | 获得一个key对应一个value的请求头 |
getHeaderNames() | Enumeration | 获取所有的请求头的键 |
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* Enumeration getHeaderNames() 获取所有的请求头的键
* 返回值Enumeration接口 (向量枚举)
* 集合:1.0-1.1 Enumeration 集合1.2 迭代器
* Iterator迭代器接口: hasNext() next()
* Enumeration接口: hasMoreElement() nextElement()
*/
Enumeration<String> enums = request.getHeaderNames();
while (enums.hasMoreElements()){
key = enums.nextElement();
String value = request.getHeader(key);
System.out.println(key+"=="+value);
}
}
4 Request获取请求参数 重点 重点 重点
方法 | 返回值 | 描述 |
---|---|---|
getParameter(表单中的name值) | String | 获得提交的参数(一个name对应一个value) |
getParameterValues(表单中的name值) | String[] | 获得提交的参数(一个name对应多个值)如:获取多选 |
getParameterMap() | Map(String,String[]) | 获得提交的参数,将提交的参数名称和对应的值存入到一个Map集合中 |
示例代码
前端代码
<body>
<form action="/web02/param" method="post">
用户名:<input type="text" name="username"><br/>
密 码:<input type="password" name="password"><br/>
爱 好:<input type="checkbox" name="hobby" value="Basketball">篮球
<input type="checkbox" name="hobby" value="football">足球
<input type="checkbox" name="hobby" value="pingpang">乒乒球 <br/>
<input type="submit">
</form>
</body>
获取请求
@WebServlet(urlPatterns = "/param")
public class ParamServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获得提交的参数(一个name对应一个value)
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username +" == " +password);
//获得提交的参数(一个name对应多个value)
String[] hobbies = request.getParameterValues("hobby");
System.out.println("hobbies = " + Arrays.toString(hobbies));
//获得提交的参数,将提交的参数名称和对应值存入到一个Map集合中
Map<String, String[]> map = request.getParameterMap();
for(String key : map.keySet()){
String[] values = map.get(key);
System.out.println(key + " == " + Arrays.toString(values));
}
}
5 Request对象接收表单请求参数的中文乱码处理
5.1 POST方式接收中文
- 产生乱码的原因:
- post方式提交的数据是在请求体中,request对象接收到数据之后,放入request的缓冲区中。缓冲区就有编码(默认ISO-8859-1:不支持中文).
- 解决方案:
- 将request的缓冲区的编码修改了即可。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//将request的缓冲区的编码修改
request.setCharacterEncoding("utf-8");
//获取请求参数
String user = request.getParameter("user");
System.out.println("user = " + user);
}
5.2 GET方式接收中文
Tomcat8.5版本之后, Tomcat自动处理了get请求的中文乱码问题
但在Tomcat8.5之前的版本中, get请求的中文乱码需要自行处理
- 产生乱码原因:
- get方式提交的数据在请求行的url后面,在地址栏上其实就已经进行了一次URL的编码了。
- 解决方案:
- 将存入到request缓冲区中的值以ISO-8859-1的方式获取到,以UTF-8的方式进行解码。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
get方式提交的数据在 请求行中
Tomcat8.5之后, Tomcat自动处理了get请求的中文乱码问题, 但在之前的Tomcat版本中,get请求的中文乱码需要自行处理
老版本Tomcat中文乱码的解决:将存入到request缓冲区中的值以ISO-8859-1的方式获取到,以UTF-8的方式进行解码。
*/
String user = request.getParameter("username"); //
//将存入到request缓冲区中的值以ISO-8859-1的方式获取到
byte[] bytes = user.getBytes("iso-8859-1");
//以UTF-8的方式进行解码
String value = new String(bytes, "utf-8");
System.out.println("user = " + user);
}
6 BeanUtils 将 map中的数据封装到 pojo类中
6.1 导包
6.2 pojo类
package cn.itcast.pojo;
import java.util.Arrays;
public class User {
private String username;
private String password;
private String[] 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 "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", hobby=" + Arrays.toString(hobby) +
'}';
}
}
6.3 页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/web0202/demo15" method="post">
用户名:<input type="text" name="username"><br/>
密 码:<input type="password" name="password"><br/>
爱 好:<input type="checkbox" name="hobby" value="Basketball">篮球
<input type="checkbox" name="hobby" value="football">足球
<input type="checkbox" name="hobby" value="pingpang">乒乒球 <br/>
<input type="submit">
</form>
</body>
</html>
6.4 servlet
package cn.itcast.web;
import cn.itcast.pojo.User;
import org.apache.commons.beanutils.BeanUtils;
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.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet("/demo15")
public class ServletDemo15 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 解决服务器给浏览器的数据中文乱码问题
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
Map<String, String[]> parameterMap = request.getParameterMap();
User user = new User();
try {
BeanUtils.populate(user, parameterMap);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(user);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
6.5 原理
7 Request域对象
Request作为域对象的API
7.1 Request作用域对象作用范围
Request对象其实就是从客户端浏览器向服务器发送的一次请求信息的封装。那么实质上向Request中所保存的数据有效期也是一次请求范围。
一次请求范围:从客户端浏览器向服务器发送一次请求,服务器针对这次请求对浏览器作出响应。当服务器作出响应之后,请求对象就销毁了,保存在其中的数据就无效了。
每次请求都会创建新的request对象, 当响应结束后立刻销毁request对象.
- API
方法 | 返回值 | 描述 |
---|---|---|
setAttribute(String name, Object obj) | void | 向Request域中保存数据 |
getAttribute(String name) | Object | 从Request域中获取数据 |
removeAttribute(String name) | void | 从Request域中移除数据 |
- 代码演示
servlet1
@WebServlet(urlPatterns = "/my1")
public class MyServlet1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//向request域对象中 存值
request.setAttribute("heima","java");
//从request域对象中 取值
Object value = request.getAttribute("heima");
System.out.println("MyServlet1 value = " + value);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
servlet2
@WebServlet(urlPatterns = "/my2")
public class MyServlet2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//从request域对象中 取值
Object value = request.getAttribute("heima");
System.out.println("MyServlet2 value = " + value);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
8 请求转发
8.1 原理
![1569730812798](imgs/web02 request_response/1569730812798.png)
8.2 请求转发的写法
通过ServletRequest对象获得RequestDispatcher对象
方法 | 返回值 | 描述 |
---|---|---|
getRequestDispatcher(String path) | RequestDispatcher | 获得RequestDispatcher对象 |
再根据RequestDispatcher中的方法进行请求转发
方法 | 返回值 | 描述 |
---|---|---|
forward(ServletRequest request, ServletResponse response) | void | 进行请求转发 |
8.3 转发的实现步骤
- request对象方法获取转发器 RequestDispatcher getRequestDispatcher("转发地址")返回值就是转发器
- 使用转发器对象的方法 forward
代码实现
servlet1
@WebServlet(urlPatterns = "/my1")
public class MyServlet1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//向request域对象中 存值
request.setAttribute("heima","java");
//从request域对象中 取值
Object value = request.getAttribute("heima");
System.out.println("MyServlet1 value = " + value);
//进行请求转发
request.getRequestDispatcher("/my2").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
servlet2
@WebServlet(urlPatterns = "/my2")
public class MyServlet2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//从request域对象中 取值
Object value = request.getAttribute("heima");
System.out.println("MyServlet2 value = " + value);
//响应回浏览器
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("我是MyServlet2 页面数据");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
9 请求转发和重定向区别
9.1 区别总结
- 请求转发是一次请求一次响应,而重定向是两次请求两次响应。
- 请求转发地址栏不会变化的,重定向地址栏发生变化。
- 请求转发路径不带工程名,重定向需要带工程名路径。
- 请求转发只能在本网站内部,重定向可以定向到任何网站。
9.2 代码演示
MyServlet1
@WebServlet(urlPatterns = "/my1")
public class MyServlet1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//向request域对象中 存值
request.setAttribute("heima","java");
//从request域对象中 取值
Object value = request.getAttribute("heima");
System.out.println("MyServlet1 value = " + value);
//进行请求转发
//request.getRequestDispatcher("/my2").forward(request, response);
//进行重定向
response.sendRedirect("/web02/my2");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
MyServlet2
@WebServlet(urlPatterns = "/my2")
public class MyServlet2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//从request域对象中 取值
Object value = request.getAttribute("heima");
System.out.println("MyServlet2 value = " + value);
//响应回浏览器
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("我是MyServlet2 页面数据");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
- 注意:
- 如果需要使用request进行值传递,需要通过请求转发完成。
- 如果页面需要跳转到其他网站上必须使用重定向, 不能使用request进行值传递。
10 客户端与服务器端地址的写法
- 什么是客户端地址:客户端直接访问服务器的地址是客户端地址
- 通过客户端访问web应用 地址必须加上web应用的名称
- 什么是服务器端地址:web应用内部访问的地址是服务器端地址
- 特点,访问时,不用写web应用名称
- 写地址时, 怎么区分是否加上web应用的名称
- 看在web应用内, 还是外
- 客户端地址
- 直接在地址栏中写url地址 --- 客户端地址
- 标签的href --- 客户端地址
- form表单的action-----客户端地址
- location.href ---- 客户端地址
- response响应对象的重定向 sendRedirect( 地址) -----客户端地址
- 目前记住一个服务器端地址:
- Request请求对象的请求转发getRequestDispatcher(转发地址) --- 服务器端地址
- servlet的映射路径--- 也是服务端地址
- 客户端地址
- 看在web应用内, 还是外
第四章 案例 用户登录注册
1 用户注册功能
1.1 分析
1.2 开发步骤
- 创建数据库数据表
- 创建新的项目
- 准备工作
- 创建包
- 添加需要jar
- 配置文件
- 功能,编写服务器程序
1.3 准备工作
sql语句
CREATE DATABASE web02_db;
USE web02_db;
CREATE TABLE tb_user(
id int primary key auto_increment,
username VARCHAR(32),
password VARCHAR(32),
nickname varchar(32)
);
INSERT INTO tb_user VALUES(null,'zhangsan','123','张三'),(null,'lisi','456','李四');
# 通过用户名,密码查询 user表
SELECT * FROM tb_user WHERE username='zhangsan' AND `password`='123'
导包和配置文件
1.4 入口页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post" action="/web0203/registerServlet">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="username"/></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password"/></td>
</tr>
<tr>
<td>昵称</td>
<td><input type="text" name="nickname"/></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"/></td>
</tr>
</table>
</form>
</body>
</html>
1.5 web层
package cn.itcast.web;
import cn.itcast.pojo.User;
import cn.itcast.service.UserService;
import cn.itcast.service.impl.UserServiceImpl;
import org.apache.commons.beanutils.BeanUtils;
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.lang.reflect.InvocationTargetException;
@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 解决服务器给浏览器的数据中文乱码问题
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
// 1 获取参数 封装到pojo类中
User user = new User();
try {
BeanUtils.populate(user, request.getParameterMap());
} catch (Exception e) {
e.printStackTrace();
}
// 2 调用业务层 添加用户
UserService userService = new UserServiceImpl();
userService.register(user);
// 3 使用重定向跳转到 登录页面
response.sendRedirect(request.getContextPath() + "/login.jsp");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
1.6 业务层
- 业务层接口
package cn.itcast.service;
import cn.itcast.pojo.User;
public interface UserService {
/**
* 添加用户
* @param user
* @return
*/
void register(User user);
}
- 业务层实现类
package cn.itcast.service.impl;
import cn.itcast.dao.UserDao;
import cn.itcast.dao.impl.UserDaoImpl;
import cn.itcast.pojo.User;
import cn.itcast.service.UserService;
public class UserServiceImpl implements UserService {
UserDao userDao = new UserDaoImpl();
@Override
public void register(User user) {
try {
userDao.register(user);
} catch (Exception e) {
e.printStackTrace();
}
}
}
1.8 数据层
- 数据层接口
package cn.itcast.dao;
import cn.itcast.pojo.User;
public interface UserDao {
void register(User user) throws Exception;
}
- 数据层实现类
package cn.itcast.dao.impl;
import cn.itcast.dao.UserDao;
import cn.itcast.pojo.User;
import cn.itcast.utils.DruidUtils;
import com.alibaba.druid.util.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import javax.management.Query;
public class UserDaoImpl implements UserDao {
QueryRunner queryRunner;
{
try {
queryRunner = new QueryRunner(DruidUtils.getDataSource());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void register(User user) throws Exception {
String sql = "insert into tb_user values(null, ?, ?, ?)";
Object[] params = {user.getUsername(), user.getPassword(), user.getNickname()};
queryRunner.update(sql, params);
}
}