回顾
1.Servlet:
作用:接收请求,回响应的服务器端的程序
2.Servlet的创建方式:
a.实现Servlet接口
b.继承HttpServlet(以后要用到的)
c.具体的实现: 配置web.xml 注解
3.继承HttpServlet方式中的doGet doPost
doGet():用于处理页面发给服务器的get请求 -> 在地址栏上直接发出的请求是get请求
doPost():用于处理页面发给服务器的post请求
4.Servlet生命周期
a.Servlet什么时候被创建:当第一次有请求的时候,Servlet被创建了,而且tomcat只创建一个Servlet对象
b.Servlet对象什么时候被销毁:关闭服务器,或者将项目从tomcat下移除
5.在Servlet生命周期过程中的三个方法
a.init()当第一次来请求的时候,访问这个Servlet,调用init
b.service()在每一次对servlet发出请求时,都会调用一次service方法
c.destory():可以用于销毁一下资源,在关闭服务器的时候或者移除项目,就会调用destory方法
6.三种映射路径的配置
a.完全匹配: /servlet1 访问servlet1时,访问路径上必须写/servlet1
b.目录匹配: /目录名
今日重点:
1.会使用Request对象获取请求参数
2.会使用Request对象解决请求参数乱码
3.会使用Request中的方法往Request域中存数据,取数据
4.会使用Request对象完成请求转发
5.会使用BeanUtils工具类将请求参数封装成javabean对象
6.会使用Response对象设置响应体
7.会使用Response对象完成重定向
3.继承HttpServlet方式中的doGet doPost
doGet():用于处理页面发给服务器的get请求 -> 在地址栏上直接发出的请求是get请求
doPost():用于处理页面发给服务器的post请求
4.Servlet生命周期
a.Servlet什么时候被创建:当第一次有请求的时候,Servlet被创建了,而且tomcat只创建一个Servlet对象
b.Servlet对象什么时候被销毁:关闭服务器,或者将项目从tomcat下移除
5.在Servlet生命周期过程中的三个方法
a.init()当第一次来请求的时候,访问这个Servlet,调用init
b.service()在每一次对servlet发出请求时,都会调用一次service方法
c.destory():可以用于销毁一下资源,在关闭服务器的时候或者移除项目,就会调用destory方法
6.三种映射路径的配置
a.完全匹配: /servlet1 访问servlet1时,访问路径上必须写/servlet1
b.目录匹配: /目录名
第一章.Request请求对象
强调:
我们在doGet和doPost中写的是处理请求和响应的具体逻辑
真正处理请求的是Request对象
真正做响应的是Response对象
1.Request概述
1.概述:在Servlet中,定义了一个HttpServletRequest接口,它继承自ServletRequest接口
2.作用:专门用于封装HTTP请求消息的.
由于HTTP请求信息分为:请求行,请求头,请求体三部分,因此在HttpServletRequest中定义了获取请求行,请求头,请求体的方法
3.用我们自己理解的话:
HttpServletRequest就是服务器中的一个请求对象,该对象封装了请求行,请求头,请求体的内容
所以我们拿到这个对象就可以调用这个对象中的get方法获取请求行,请求头,请求体中的内容
只有将这些请求的信息获取出来,我们才能拿到具体的请求数据参与代码的逻辑处理
1.1.Request的组成
1.请求行:包含请求方式(get/post) 请求的路径 http协议/版本号
2.请求头:都是键值对,是客户端传递给服务器端的指导性信息
3,请求体:
POST请求是有请求体的,请求体中的请求参数才是我们真正要操作的数据
GET请求没有请求体,提交的请求参数在地址栏上
1.2.Request的作用
1.获取HTTP请求三部分中的数据(行,头,体),主要是获取请求体中的请求参数
2.进行请求转发
3.作用域对象对数据进行存取
2.Request获取HTTP请求内容的方法
2.1.获取请求行方法:
方法名 | 说明 |
---|
getMethod() | 获取请求方式 |
getContextPath() | 获取当前应用上下文路径(在application context中设置的名字) |
getRequestURI() | 获取请求地址,不带主机名 |
getRequestURL() | 获取请求地址,带主机名 |
@WebServlet("/request1")
public class Request01Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String method = request.getMethod();
System.out.println(method);
System.out.println("=========================");
String contextPath = request.getContextPath();
System.out.println(contextPath);
System.out.println("=======================");
String requestURI = request.getRequestURI();
System.out.println(requestURI);
System.out.println("===================================");
StringBuffer requestURL = request.getRequestURL();
System.out.println(requestURL);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/day07_request_response/request1" method = "get">
<input type="submit" value="提交">
</form>
</body>
</html>
2.2.获取请求头信息方法
方法名 | 说明 |
---|
getHeader(String name) | 根据请求的key获取对应的value |
@WebServlet("/request2")
public class Request02Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String host = request.getHeader("Host");
System.out.println(host);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.3.获取请求体中的请求参数(重点)
1.什么是请求参数
请求参数时客户端提交给服务器的数据 例如:"username=aobama&password=1234"
2.请求参数常见的有两种形式:
a.表单提交之后地址栏上 ? 后面的请求参数 -> get请求
b.使用post请求时,请求体中的请求参数 -> post请求
c.Ajax异步请求携带的请求参数(后面会学习)
3.注意:
a.不管是哪种方式提交请求,请求参数都是key=value&key=value形式
b.key其实指的是页面上的name属性值
value指的是页面上的value属性值
方法名 | 返回值类型 | 方法描述 |
---|
request.getParameter(“请求参数的name属性名”) | String | 根据提交参数的name获取对应的value |
request.getParameterValues(“请求参数的name属性名”) | String[] | 根据提交参数的name获取多个value |
request.getParameterMap() | Map<String,String[]> | 获取提交请求的所有参数,以键值对的方式 存到map中 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>获取提交参数</title>
</head>
<body>
<a href="/day07_request_response/request3?username=aobama&password=1234">访问request3</a><br/>
<form action="/day07_request_response/request3" method="get">
用户名<input type="text" name="username"/><br/>
密码<input type="text" name="password"/><br/>
昵称<input type="text" name="nickname"/><br/>
邮箱<input type="text" name="email"/><br/>
兴趣爱好<input type="checkbox" name="hobby" value="basketball"/>篮球
<input type="checkbox" name="hobby" value="football"/>足球
<input type="checkbox" name="hobby" value="yumaoball"/>羽毛球
<input type="checkbox" name="hobby" value="pingpangball"/>乒乓球<br/>
<button type="submit">提交</button>
</form>
</body>
</html>
@WebServlet("/request3")
public class Request03Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+"..."+password);
System.out.println("======================================");
String[] hobbies = request.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
System.out.println("======================================");
Map<String, String[]> map = request.getParameterMap();
Set<Map.Entry<String, String[]>> entries = map.entrySet();
for (Map.Entry<String, String[]> entry : entries) {
System.out.println(entry.getKey()+"..."+Arrays.toString(entry.getValue()));
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.4.解决获取请求参数乱码
2.4.1.为什么会发生请求参数乱码问题
说明:
因为客户端发送请求给服务器的时候需要进行编码,将字符串编码成二进制才能在网络上传输,而服务器在接收到二进制的请求参数之后,需要进行解码才能获取到真正的请求参数
在这个过程中,如果保证客户端编码和服务端解码使用的字符编码集一样的话,就不会出现乱码了
而发生乱码的原因是因为客户端编码和服务端解码采用的字符编码集不一致导致的,所以此时就乱码了
浏览器对中文处理采用的是UTF-8编码
tomcat服务器对中文的处理使用ISO8895-1编码
2.4.2.怎么解决请求参数乱码问题(主要针对post请求)
1.为什么get请求时,服务器获取到的请求参数中文不会乱码;post请求,就会乱码
当前我们使用的是tomcat8版本或者以上,我们无需考虑get请求乱码问题,因为tomcat8及以上版本解决了get请求乱码问题
所以我们只考虑解决post请求乱码问题即可
2.解决方式:在获取请求参数之前,加上以下方法:
方法名 | 说明 |
---|
request.setCharacterEncoding(“UTF-8”) | 将获取到的请求参数变成utf-8格式 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>请求参数为中文</title>
</head>
<body>
<form action="/day07_request_response/request4" method="post">
用户名<input type="text" name="username"/><br/>
密码<input type="text" name="password"/><br/>
<button type="submit">提交</button>
</form>
</body>
</html>
@WebServlet("/request4")
public class Request04Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+"..."+password);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
3.请求转发
3.1.什么是请求转发
1.概述:请求转发是从一个资源跳转到另外一个资源的技术,在这个过程中浏览器不会发起新的请求,浏览器根本不知道服务器内部干了啥
因此,请求转发浏览器地址栏不会发生改变
2.服务器请求转发行为:其实就是从给一个服务器资源,跳转到另一个服务器资源的过程
3.注意:
请求转发是服务器内部行为,所以请求转发不能离开当前web项目,只要是在当前项目下,请求转发都可以转过去,包括WEB-INF
3.2.请求转发方法
方法名 | 说明 |
---|
RequestDispacher getRequestDispacher(String path) | 获取请求转发器对象 参数:path指的是要转到哪个servlet资源上去或者哪个页面上去 1.如果要转发到另一个servlet上,就写servlet对应的url-pattern 2.如果要转发到某一个页面上,就写这个也的路径 |
forward(request对象,response对象) | 实现请求转发方法 此方法是RequestDispacher对象的方法 |
3.3.请求转发演示
需求:浏览器发请求给request5,request5将请求转发到request6中,让request做响应
@WebServlet("/request5")
public class Request05Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/index.html").forward(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
@WebServlet("/request6")
public class Request06Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("I am request6");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
3.4.总结
1.请求转发的跳转是服务器内部行为,在这个过程中浏览器只会发起一次请求
2.请求转发只能跳转到本项目的资源中去,包括WEB-INF下的资源
3.请求转发不会改变地址栏的地址
4.Request域对象
1.概述:
我们之前学了ServletContext域对象,这个是全局域,全局域是整个项目的所有动态资源都能共享的一个范围;
但是请求域的范围只是在一次请求中共享数据,如果发起了第二个请求,请求域中的数据失效了
2.作用:存储数据,但是数据只在同一次请求中有效,第二次请求数据失效
4.1.Request域对象方法
方法名 | 说明 |
---|
void setAttribute(String key,Object value) | 存储数据 |
Object getAttribute(String key) | 从域中获取数据 |
void removeAttribute(String key) | 从域中删除数据 |
4.2.Request域对象演示
需求:request7中在Request域对象中存储一个数据,在request8中获取请求域中的数据
@WebServlet("/request7")
public class Request07Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("username","root");
request.getRequestDispatcher("/request8").forward(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
@WebServlet("/request8")
public class Request08Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object value = request.getAttribute("username");
System.out.println(value);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
第二章.标准JavaBean
1.JavaBean是Java语言编写类的一种标准规范.符合JavaBean的类,要求:
a.类必须是具体的和公共的
b.并且具有无参构造,有参构造
c.要求成员变量私有化,并且要提供对应的get/set方法
d.需要实现序列化接口
2.将来开发我们需要分包分类:好维护->包名都是公司域名倒着写
com.atguigu.dao -> 专门放和数据库打交道的类->此类中写的都是jdbc代码
com.atguigu.service -> 专门存放service相关类->业务类
com.atguigu.controller->专门放接收请求,回响应的类 -> servlet类
com.atguigu.utils-> 专门方法工具类
com.atguigu.javabean -> 专门方法实体类->专门放javabean类的
第三章.BeanUtils工具类的使用
1.问题描述:
我们将来需要将页面上的数据提交给服务器,服务器可以一次性将提交给服务器的请求参数获取到,将数据最终放到数据库中
2.怎么将提交给服务器的数据一次都获取到呢?
request.getParameterMap()->一次获取所有提交的数据->此方法key为name属性值,value是一个数据
3.sql语句存数据:insert into 表名(列名,列名)values(?,?)
?需要接收map集合中的value
所以我们需要遍历Map,获取map的value(数组),还得遍历数组将数组中的具体数据获取出来放到sql中,进行添加->真恶心,真麻烦,真der
4.解决:->BeanUtils工具类
a.我们可以定义一个javabean类,属性和页面上提交的参数保持一直
b.调用request.getParameterMap()->一次获取所有提交的数据,返回一个Map集合
c.使用工具类,一次将map中的value数组中的值封装到javabean中(遍历value数组给javabean的属性赋值)
d.调用javabean中的get方法将属性值取出,放到sql中
1.BeanUtils工具类的作用:
不用遍历Map的前提下,直接将Map的value填充到JavaBean对象中
2.使用:
a.导jar包
原来存放lib的文件夹都创建在当前项目下
现在我们的习惯将lib放到WEB-INF下
b.调用工具类中的方法实现封装数据
方法名 | 说明 |
---|
BeanUtils.populate(Javabean对象,Map集合) | 将Map集合中的数据直接封装到Javabean中 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册</title>
</head>
<body>
<form action="/day07_request_response/beanutils1" method = "get">
编号:<input type="text" name="id"/><br/>
姓名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
住址:<input type="text" name="address"/><br/>
<input type="submit" value = "注册">
</form>
</body>
</html>
public class Person {
private Integer id;
private String name;
private Integer age;
private String address;
public Person() {
}
public Person(Integer id, String name, Integer age, String address) {
this.id = id;
this.name = name;
this.age = age;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
@WebServlet("/beanutils1")
public class BeanUtilsServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, String[]> map = request.getParameterMap();
Person person = new Person();
try {
BeanUtils.populate(person, map);
System.out.println(person);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
注意:如果想使用BeanUtils工具类,那么javabean中的属性要对应页面上提交的参数,属性名和页面上的name属性值最好一致
第四章.Response响应对象
1.Response响应对象介绍
1.1.Response概念
1.在Servlet中,有一个HttpServletResponse接口,继承自ServletResponse接口,专用来封装HTTP响应信息
2.由于HTTP响应信息分为响应行,响应头,响应体三部分,因此,在HttpServletResponse接口中定义了向客户端设置响应行,头,体的方法
3.请求:客户端往服务端发起的->作为服务端接收请求,request对象中都是getxxx的方法,用来获取请求数据
响应:服务器将数据给客户端->作为服务器来说,response对象应该有很多setxxx的方法,用来往客户端设置响应数据
1.2.Response作用
Response就是一个服务端的对象,给客户端设置行,头,体的数据
2.Response使用
2.1.设置响应状态码(了解即可)
1.注意:Tomcat服务器,根据Servlet的运行结果,自动设置状态码
2.常见的状态码:
200:响应成功
302:重定向
404:资源未找到
500:服务器内部错误
方法名 | 说明 |
---|
response.setStatus(状态码) | 设置响应行中的响应状态码 |
@WebServlet("/response1")
public class Response01Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(1 / 0);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.2.设置响应头(了解)
响应头的数据格式 : k:v
方法名 | 说明 |
---|
setHeader(String key,String value) | 设置响应头的key和value |
@WebServlet("/response2")
public class Response02Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setHeader("myHeader","header");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.3.设置响应体(重要)
2.3.1.方法一.使用字符输出流做响应
方法名 | 说明 |
---|
PrintWriter getWriter() | 使用字符流作出响应,响应中文有乱码 |
@WebServlet("/response3")
public class Response03Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter writer = response.getWriter();
writer.write("<!DOCTYPE html>\n" +
"<html lang=\"en\">\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>Title</title>\n" +
"</head>\n" +
"<body>\n" +
"<h1>response</h1>\n" +
"</body>\n" +
"</html>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.3.2.方法二.解决响应中文乱码
方法名 | 说明 |
---|
response.setContentType(“text/html;charset=utf-8”) | 设置响应体,解决响应中文乱码 |
@WebServlet("/response4")
public class Response04Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("我是响应的response4");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.3.3.方法三.使用字节流做响应
字符流:针对文本文档
字节流:万能流,使用字节流可以响应文本,图片等
使用字节流做响应,响应中文不乱码
方法名 | 说明 |
---|
OutputStream getOutputStream() | 获取字节流对象 |
@WebServlet("/response5")
public class Response05Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletOutputStream os = response.getOutputStream();
ServletContext context = getServletContext();
String path = context.getRealPath("24.jpg");
FileInputStream fis = new FileInputStream(path);
byte[] bytes = new byte[1024];
int len;
while((len = fis.read(bytes))!=-1){
os.write(bytes,0,len);
}
fis.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.3.4.字节流和字符流互斥问题
1.描述:
一个doGet只能获取一次,要不都是字节流,要不都是字符流,禁止同时使用
2.互斥原因:
response中的流都是有缓冲区的
如果字节流和字符流同时使用,response对象就一个
那么我们使用char数组还是byte数组呢?此时response蒙了
2.4.设置浏览器重定向
重定向是由项目中的一个资源跳转到另外一个资源上,在这个过程中客户端会发起新的请求,重定向状态码302
方法名 | 说明 |
---|
response.sendRedirect(“重定向的资源路径”) | 请求重定向到另外一个资源中去 |
需求:浏览器发请求给response6 然后从response6重定向到response7.让response7做响应
@WebServlet("/response6")
public class Response06Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect(request.getContextPath()+"/response7");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
@WebServlet("/response7")
public class Response07Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("你好,我是response7");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.5.重定向和请求转发区别
1. 重定向会由浏览器发起新的请求,而请求转发不会发起新的请求
2. 重定向可以访问任意互联网资源,而请求转发只能访问本项目资源
3. 重定向不能访问本项目的WEB-INF内的资源,而请求转发可以访问本项目的WEB-INF内的资源
4. 发起重定向的资源和跳转到的目标资源没在同一次请求中,所以重定向不能在请求域中使用;而发起请求转发的资源和跳转到的目标资源在同一次请求中,所以请求转发可以在请求域中使用