Request是请求对象,Response是响应对象。
- request:==获取==请求数据
- 浏览器会发送HTTP请求到后端服务器[Tomcat]
- HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]
- 后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中
- 所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数
- 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务
- response:==设置==响应数据
- 业务处理完后,后台就需要给前端返回业务处理的结果即响应数据
- 把响应数据封装到response对象中
- 后台服务器[Tomcat]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果
- 浏览器最终解析结果,把内容展示在浏览器给用户浏览
- request:==获取==请求数据
- 浏览器会发送HTTP请求到后台服务器[Tomcat]
- HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]
- 后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中
- 所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数
- 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务
- response:==设置==响应数据
- 业务处理完后,后台就需要给前端返回业务处理的结果即响应数据
- 把响应数据封装到response对象中
- 后台服务器[Tomcat]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果
- 浏览器最终解析结果,把内容展示在浏览器给用户浏览
要运行req和resp,需要在service方法中添加doGet和doPost方法
Request对象:
- doGet:
//request的API:
protectedvoiddoGet(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
// String getMethod():获取请求方式: GET
Stringmethod=req.getMethod();
System.out.println(method);//GET
// String getContextPath():获取虚拟目录(项目访问路径):/request-demo
StringcontextPath=req.getContextPath();
System.out.println(contextPath);
// StringBuffer getRequestURL(): 获取URL(统一资源定位符):http://localhost:8080/request-demo/req1
StringBufferurl=req.getRequestURL();
System.out.println(url.toString());
// String getRequestURI():获取URI(统一资源标识符): /request-demo/req1
Stringuri=req.getRequestURI();
System.out.println(uri);
// String getQueryString():获取请求参数(GET方式): username=zhangsan
StringqueryString=req.getQueryString();
System.out.println(queryString);
2.doPost
获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法 --getInputStream()
获取字符输入流,如果前端发送的是纯文本数据,则使用该方法 --getReader()
想获取到请求体的内容该如何实现?
具体实现的步骤如下:
1.准备一个页面,在页面中添加form表单,用来发送post请求
2.在Servlet的doPost方法中获取请求体数据
3.在doPost方法中使用request的getReader()或者getInputStream()来获取
4.访问测试
1.在form标签里加入action="tomcat_demo_war/demo2" ——servlet类的虚拟路径
method="post" ——请求方式
BufferedReaderbr=req.getReader();
Stringresult=br.readLine();
System.out.println(result);
BufferedReader流是通过request对象来获取的,当请求完成后request对象就会被销毁,request对象被销毁后,BufferedReader流就会自动关闭,所以此处就不需要手动关闭流了。
小结
HTTP请求数据中包含了请求行、请求头和请求体,针对这三部分内容,Request对象都提供了对应的API方法来获取对应的值:
- 请求行
- getMethod()获取请求方式
- getContextPath()获取项目访问路径
- getRequestURL()获取请求URL
- getRequestURI()获取请求URI
- getQueryString()获取GET请求方式的请求参数
- 请求头
- getHeader(String name)根据请求头名称获取其对应的值
- 请求体
- 注意: ==浏览器发送的POST请求才有请求体==
- 如果是纯文本数据:getReader()
- 如果是字节数据如文件数据:getInputStream()
请求数据则是包含请求行、请求头和请求体的所有数据
请求参数是请求数据中的部分内容
如果是GET请求,请求参数在请求行中 如果是POST请求,请求参数一般在请求体中
GET请求方式和POST请求方式区别主要在于获取请求参数的方式不一样,是否可以提供一种==统一==获取请求参数的方式,从而==统一==doGet和doPost方法内的代码?
/**
* request 通用方式获取请求参数
*/
//获取所有参数Map集合
Map<String,String[]>getParameterMap()
//根据名称获取参数值(数组)
String[] getParameterValues(Stringname)
//根据名称获取参数值(单个值)
StringgetParameter(Stringname)
//因为参数的值可能是一个,也可能有多个,所以Map的值的类型为String数组。
protectedvoiddoGet(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
//GET请求逻辑
System.out.println("get....");
//1. 获取所有参数的Map集合
Map<String, String[]>map=req.getParameterMap();
for (Stringkey : map.keySet()) {
// username:zhangsan lisi
System.out.print(key+":");
//获取值
String[] values=map.get(key);
for (Stringvalue : values) {
System.out.print(value+" ");
}
System.out.println();
}
}
中文乱码解决方案
- POST请求和GET请求的参数中如果有中文,后台接收数据就会出现中文乱码问题
GET请求在Tomcat8.0以后的版本就不会出现了
- POST请求解决方案是:设置输入流的编码
request.setCharacterEncoding("UTF-8");
注意:设置的字符集要和页面保持一致
- 通用方式(GET/POST):需要先解码,再编码
new String(username.getBytes("ISO-8859-1"),"UTF-8");
- URL编码实现方式:
- 编码:
URLEncoder.encode(str,"UTF-8");
- 解码:
URLDecoder.decode(s,"ISO-8859-1");
Request请求转发
(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A处理完请求后将请求发给资源B
(3)资源B处理完后将结果响应给浏览器
(4)请求从资源A到资源B的过程就叫==请求转发==
req.getRequestDispatcher("资源B路径").forward(req,resp);
//dispatcher 调度员
请求转发资源间共享数据:使用Request对象
此处主要解决的问题是把请求从/req5转发到/req6的时候,如何传递数据给/req6。
需要使用request对象提供的三个方法:
- 存储数据到request域[范围,数据是存储在request对象]中
void setAttribute(String name,Object o);
//Attribute 属性
- 根据key获取值
Object getAttribute(String name);
- 根据key删除该键值对
void removeAttribute(String name);
System.out.println("demo1");
request.setAttribute("sb","hello");
request.getRequestDispatcher("/demo2").forward(request,response);
Objectaa=req.getAttribute("sb");
Reqsonse对象:
对于Response我们需要学习如下内容:
- Response设置响应数据的功能介绍
- Response完成重定向
- Response响应字符数据
- Response响应字节数据
HTTP响应数据总共分为三部分内容,分别是==响应行、响应头、响应体==
voidsetStatus(intsc);//响应行: 设置响应状态码
voidsetHeader(Stringname,Stringvalue);//响应头: 设置响应头键值对 Content-type:text/html (设置识别为html)
PrintWritergetWriter(); ServletOutputStreamgetOutputStream();
//响应体:获取字符,字节输出流
//重定向
//1.设置响应状态码 302
response.setStatus(302);
//2. 设置响应头 Location
response.setHeader("Location","/request-demo/resp2");
//简化版重定向
resposne.sendRedirect("/request-demo/resp2");
重定向特点:
浏览器地址栏路径发送变化
当进行重定向访问的时候,由于是由浏览器发送的两次请求,所以地址会发生变化
可以重定向到任何位置的资源(服务内容、外部均可)
因为第一次响应结果中包含了浏览器下次要跳转的路径,所以这个路径是可以任意位置资源。
两次请求,不能在多个资源使用request共享数据
因为浏览器发送了两次请求,是两个不同的request对象,就无法通过request对象进行共享数据
浏览器使用:需要加虚拟目录(项目访问路径)
服务端使用:不需要加虚拟目录
响应数据:
//相应字符数据
response.setContentType("text/html;charset=utf-8");//设置编码规范,可以写中文
PrintWriterwriter=response.getWriter();
//content-type,告诉浏览器返回的数据类型是HTML类型数据,这样浏览器才会解析HTML标签
response.setHeader("content-type","text/html");
writer.write("<h1>aaa</h1>");
writer.write("aaaa");
//响应字节数据
//1.读取文件
FileInputStreamfis=newFileInputStream("d://a.jpg");
//2.获取response字节输出流
ServletOutputStreamos=response.getOutputStream();
//3.完成流的copy
byte[] buff=newbyte[1024];
intlen=0;
while((len=fis.read(buff))!=-1){
os.write(buff,0,len);
}
fis.close();
//使用依赖完成流的copy
/*
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
*///fis:输入流 os输出流
IOUtils.copt(fis,os);
用户登录案例:
项目流程:
1.创建maven项目
2.编写HTML、css静态页面
3.创建数据表 创建实体类
4.在项目的pom.xml导入mybatis和mysql驱动坐标
5.创建mybatis-config.xml核心配置文件,UserMapper.xml映射文件,UserMapper接口
<?xmlversion="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--起别名-->
<typeAliases>
<packagename="com.yz.pojo"/>
</typeAliases>
<environmentsdefault="development">
<environmentid="development">
<transactionManagertype="JDBC"/>
<dataSourcetype="POOLED">
<propertyname="driver"value="com.mysql.jdbc.Driver"/>
<propertyname="url"value="jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true"/>
<propertyname="username"value="root"/>
<propertyname="password"value="2002926yz"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--扫描mapper-->
<packagename="com.yz.mapper"/>
</mappers>
</configuration>
6.在UserMapper接口中提供方法
/**
* 根据用户名和密码查询用户对象
* @param username
* @param password
* @return
@Param注解的作用:用于传递参数,是方法的参数可以与SQL中的字段名相对应。
*/
@Select("select * from tb_user where username = #{username} and password = #{password}")
Userselect(@Param("username") Stringusername,@Param("password") Stringpassword);
- 编写Servlet
WebServlet("/loginServlet")
publicclassLoginServletextendsHttpServlet {
@Override
protectedvoiddoGet(HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException {
//1. 接收用户名和密码
Stringusername=request.getParameter("username");
Stringpassword=request.getParameter("password");
//2. 调用MyBatis完成查询
//2.1 获取SqlSessionFactory对象
Stringresource="mybatis-config.xml";
InputStreaminputStream=Resources.getResourceAsStream(resource);
SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder().build(inputStream);
//2.2 获取SqlSession对象
SqlSessionsqlSession=sqlSessionFactory.openSession();
//2.3 获取Mapper
UserMapperuserMapper=sqlSession.getMapper(UserMapper.class);
//2.4 调用方法
Useruser=userMapper.select(username, password);
//2.5 释放资源
sqlSession.close();
//获取字符输出流,并设置content type
response.setContentType("text/html;charset=utf-8");
PrintWriterwriter=response.getWriter();
//3. 判断user释放为null
if(user!=null){
// 登陆成功
writer.write("登陆成功");
}else {
// 登陆失败
writer.write("登陆失败");
}
}
@Override
protectedvoiddoPost(HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException {
this.doGet(request, response);
}
}
8.SqlSessionFactory工具类抽取
Stringresource="mybatis-config.xml";
InputStreaminputStream=Resources.getResourceAsStream(resource);
SqlSessionFactorysqlSessionFactory=new
SqlSessionFactoryBuilder().build(inputStream);
//重复代码
//抽取:
publicclassSqlSessionFactoryUtils {
privatestaticSqlSessionFactorysqlSessionFactory;
static {
//静态代码块会随着类的加载而自动执行,且只执行一次
try {
Stringresource="mybatis-config.xml";
InputStreaminputStream=Resources.getResourceAsStream(resource);
sqlSessionFactory=newSqlSessionFactoryBuilder().build(inputStream);
} catch (IOExceptione) {
e.printStackTrace();
}
}
publicstaticSqlSessionFactorygetSqlSessionFactory(){
returnsqlSessionFactory;
}
}
//调用:
SqlSessionFactorysqlSessionFactory=SqlSessionFactoryUtils.getSqlSessionFactory();
项目目录结构