Request(请求)&Response(响应)
- Resquest:获取请求数据
- Response:设置响应数据
Request继承体系
- Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法中
- 使用request对象,查阅JavaEEAPI文档的HttpServletRequest接口
Request获取请求数据
请求数据分为三部分:
- 请求行:GET/request-demo/req1?username=zhangsan HTTP/1.1
//String getMethod():获取请求方式 String method=req.getMethod(); System.out.println(method); //String getContextPath():获取虚拟目录(项目访问路径) String contextPath=req.getContextPath(); System.out.println(contextPath); //StringBuffer getRequestURL():获取URL(统一资源定位符) StringBuffer url=req.getRequestURL(); System.out.println(url.toString()); //String getRequestURI():获取URI(统一资源标识符) String uri=req.getRequestURI(); System.out.println(uri); //String getQueryString():获取请求参数(GET方式) String queryString=req.getQueryString(); System.out.println(queryString); /* GET /request-demo http://localhost:8080/request-demo/req1 /request-demo/req1 username=zhangsan */
- 请求头
//获取请求头:user-agent:浏览器的版本信息 String agent=req.getHeader("user-agent"); System.out.println(agent);
- 请求体
//获取post 请求体:请求参数 //1.获取字符输入流 BufferedReader br=req.getReader(); //2.读取数据 String line=br.readLine(); System.out.println(line);
Request通用方式获取请求参数
//1.获取所有参数的Map集合
Map<String,String[]> map=req.getParameterMap();
for (String key:map.keySet()){
//username:zhangsan...
System.out.print(key+":");
//获取值
String[] values=map.get(key);
for (String value:values){
System.out.print(value+" ");
}
System.out.println();
}
//2.根据key获取参数值(数组)
String[] hobbies = req.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
//3.根据参数,获取单个参数值
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username);
System.out.println(password);
Request请求参数中文乱码
-
Post解决方案
//设置字符输入流的编码 request.setCharacterEncoding("UTF-8");
-
通用方式(GET/POST):先编码,再解码
//3.1先对乱码数据进行编码:转为字节数组 byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1); //3.2 字节数组解码 username=new String(bytes,StandardCharsets.UTF_8); System.out.println("解决乱码后:"+username);
URL编码
- 将字符串按照编码方式转为二进制
- 每个字节转为2个16进制数并在前边加上%
Tomcat 8.0之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8
请求转发(forword)
- 一种在服务器内部的资源跳转方式
- 实现方式
req.getRequestDispatcher("资源B路径").forward(req,resp);
- 请求转发资源间共享数据:使用Request对象
void setAtribule(Sting name, Object a): 存储数据到 request域中
Object getAtribute(String name): 根据 key,获取值
void.removeAttribute(String name): 根据 key,删除该键值对 - 请求转发特点:
浏览器地址栏路径不发生变化
只能转发到当前服务器的内部资源
一次请求,可以在转发的资源间使用reguest共享数据
Response设置响应数据功能
响应数据分为3部分:
- 响应行: HTTP/1.1 200 OK
void setStatus(intsc) : 设置响应状态码 - 响应头: Content-Type: text/html
void setHeader(String name, String value) : 设置响应头键值对 - 响应体:
<html><head>head><body></body></html>
- PrintWriter getWriter(): 获取字符输出流
- ServletOutpytStream getOutputStream(): 获取字节输出流
Response完成重定向
- 重定向:一种资源跳转方式
- 实现方式:
//重定向 //1.设置响应状态码 response.setStatus(302); //2.设置响应头 Location response.setHeader("Location","/request-demo/resp1"); //简化方式 response.sendRedirect("/request-demo/resp1");
- 重定向特点:
- 浏览器地址栏路径发生变化
- 可以重定向到任意位置的资源 (服务器内部、外部均可)
- 两次请求,不能在多个资源使用request共享数据
资源路径问题
明确路径给谁用
- 浏览器使用:需要加虚拟目录(项目访问路径)
- 服务端使用: 不需要加虚拟目录(如转发)
动态获取虚拟目录
String contextPath = request.getContextPath();
Response响应字符数据
- 使用
- 通过Response对象获取字符输出流
PrintWriter writer = resp.getWriter();
- 写数据
writer.write("aaa");
- 通过Response对象获取字符输出流
- 注意:
- 该流不需要关闭,随着响应结束,response对象销毁,由服务器关闭
- 中文数据乱码:原因通过Response获取的字符输出流默认编码: ISO-8859-1
resp.setContentType("text/html;charset=utfi-8");
Response响应字节数据
- 使用:
- 通过Response对象获取字符输出流
SerletOutputStream outputStream = resp.getOutputStream();
- 写数据
outputStream.write(字节数据);
- 通过Response对象获取字符输出流
- lOUtils工具类使用:
- 导入坐标
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency>
- 使用:
IOUtils.copy(输入流,输出流);
- 导入坐标
案例
用户登录
- 流程说明
- 用户填写用户名密码,提交到LoginServlet
- 在 LoginServlet中使用 MyBatis查询数据库,验证用户名密码是否正确
- 如果正确,响应“登录成功”,如果错误,响应“登录失败”
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解决post乱码
request.setCharacterEncoding("UTF-8");
//1.接收用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
//2.调用MyBatis
//2.1获取SqlSessionFactory对象
String resource="mybatis-config.xml";
InputStream inputStream= Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//2.2获取SqlSession对象
SqlSession sqlSession=sqlSessionFactory.openSession();
//2.3获取mapper
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
//2.4调用方法
User user=userMapper.select(username,password);
//2.5释放资源
sqlSession.close();
//获取字符输出流,并设置content type
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
//3.判断user是否为null
if(user!=null){
//登陆成功
writer.write("登陆成功");
}else {
//登陆失败
writer.write("登陆失败");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
用户注册
- 流程说明
- 用户填写用户名、密码等信息,点击注册按钮,提交到 ReqisterServlet
- 在RegisterServlet 中使用 MyBatis 保存数据
- 保存前,需要判断用户名是否已经存在: 根据用户名查询数据库
@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解决post乱码
request.setCharacterEncoding("UTF-8");
//1.接收用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
//封装用户数据
User user=new User();
user.setUsername(username);
user.setPassword(password);
//2.调用mapper根据用户名查询用户
//2.1获取SqlSessionFactory对象
String resource="mybatis-config.xml";
InputStream inputStream= Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//2.2获取SqlSession对象
SqlSession sqlSession=sqlSessionFactory.openSession();
//2.3获取mapper
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
//2.4调用方法
User user1 = userMapper.selectByUsername(username);
//3.判断用户对象是否为null
if (user1==null){
//用户不存在,添加用户
userMapper.add(user);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("注册成功");
}else {
//用户存在,给出提示信息
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("用户已存在");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
代码优化
配置SqlSessionFactory工具类
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
//静态代码块随着类的加载而执行,且只执行一次
static {
try {
String resource="mybatis-config.xml";
InputStream inputStream= Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}