HTTP超文本传输协议
概念:Hyper Text Tranfer Protocol 超文本传输协议
- 传输协议:定义了,客户端和服务器端通信是,发送数据的格式
- 特点:
- 基于TCP/IP的高级协议
- 默认端口号:80
- 基于请求/响应模型的:一次请求对应一次响应
- 无状态:每次请求之间相互独立,不能交互数据
- 历史版本:
- 每一次请求响应都会建立新的连接
- 复用连接
请求消息数据格式
-
请求行
-
请求方式 请求url 请求协议/版本 -
GET/login.html HTTP/1.1 -
请求方式:
- HTTP协议中有7种请求方式,常用的有两种
- GET:
- 请求参数在请求行中,在url后
- 请求的url长度有限制的
- 不是很安全
- POST:
- 请求参数在请求体中
- 请求的url长度没有限制
- 相对安全
-
请求头:客户端浏览器告诉服务器一些信息
- 请求头名称:请求头值
- 常见的请求头:
- User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
- 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
- Referer: http://localhost:8080/MyApps/login.html
-
请求空行
- 空行:用于分割POST请求的请求头,和请求体的。
-
请求体(正文)
-
字符串格式: POST /MyApps/ser03 HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 12
Origin: http://localhost:8080
Connection: keep-alive
Referer: http://localhost:8080/MyApps/login.html
Cookie: Idea-4311a65=5ac6d3b1-7c53-43e0-b438-60c6c2dbe879
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
USERNAME=ads
响应消息数据格式
Request
-
request对象和response对象的原理
- request和response对象是由服务器创建的,我们来使用它们
- request对象来获取请求消息,response对象用来设置响应消息
-
request对象继承体系结构
- ServletRequest —接口
- ? | 继承
- HttpServletRequest —接口
- ? | 实现
- org.apache.catalina.connector.CoyoteInputStream 类(Tomcat)
-
request:
-
获取请求消息数据
-
获取请求行数据
- GET /MyApps/demo01?name=qin HTTP/1.1
- 方法:
- 获取请求方式:GET
- 获取虚拟目录:/MyApps
- 获取Servlet路径:/demo1
- 获取get方式的请求参数:name=qin
- 获取请求的uri:/MyApps/demo1
- String getRequestURI():/MyApps/demo1
- StringBuffer getRequestURL():http://localhost/MyApps/demo1
- URL:统一资源定位符:http://localhost/MyApps/demo1
- URI:统一资源标识符(范围更大):/MyApps/demo1
- 获取协议以及版本 HTTP/1.1
- 获取客户机的IP地址
-
获取请求头数据
- 方法:
- String getHeader(String name):通过请求头的名称获取请求头的值
- Enumeration<String> getHeaderNames():获取所有的请求头名称
-
获取请求体数据
-
其他功能
-
获取请求参数通用方式(无论GET或者POST):
-
String getParameter(String name):根据参数名称获取参数值 username=qin&password=123 -
String getParameterValues(String name):根据参数名称获取参数值的数组 hobby=xx&hobby=game -
Enumeration<String> getParameterNames():获取所有请求的参数名称 -
Map<String,String[]> getParameterMap():获取所有参数的map集合 -
中文乱码问题 @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
System.out.println(username);
try {
response.setCharacterEncoding("GBK");
} catch (Exception e) {
e.printStackTrace();
}
response.getWriter().write(username);
}
}
-
请求转发:一种在服务器内部的资源跳转方式
- 步骤:
- 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher对象来进行转发:RequestDispatcher.forward(ServletRequest request,ServletResponse response)
- 特点:
- 浏览器地址栏路径没有发生变化
- 只能访问转发到当前服务器内部资源中
- 有转发也是一次请求
-
共享数据:
- 域对象:一个有作用范围的对象,可以在范围内共享数据
- request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
- 方法:
- setAttribute(String name,Object obj):存储数据
- getAttitude(String name):通过键获取值
- void removeAttribute(String name):通过键移除键值对
-
获取ServletContext:
- ServletContext getServletContext()
小案例:用户登录
-
用户登录案例需求:
- 编写login.html登录页面
- username&password 两个输入框
- 使用Druid数据库连接池技术,操作mysql,day14数据库中user表
- 使用jdbcTemplate技术封装JDBC
- 登录成功跳转到SuccessServlet展示:登录成功!
- 登录失败跳转到FailServlet展示:登录失败,用户名或密码错误
-
分析 -
开发步骤:
-
创建项目,导入html页面,配置文件,jar包 -
创建数据库环境 create database day14;
use day14;
create table User(
id int primary key auto_increment not null,
username varchar(32),
pwd varchar(32)
)
-
创建包cn.domain,创建类User package cn.domain;
public class User {
private String id;
private String username;
private String password;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
-
创建包cn.op,创建UserOp, package cn.util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCUtils {
private static DataSource ds;
static {
try {
Properties pro = new Properties();
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druif.properties");
pro.load(is);
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static DataSource getDataSource(){
return ds;
}
public static Connection getConnectyion() throws SQLException {
return ds.getConnection();
}
}
-
创建包cn.op,创建类UserOp,提供login方法 package cn.op;
import cn.domain.User;
import cn.util.JDBCUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
public class UserOp {
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
public User login(User loginUser){
try {
String sql = "select * from user where username = ? and pwd = ?;";
User user = template.queryForObject(sql,
new BeanPropertyRowMapper<User>(User.class),
loginUser.getUsername(), loginUser.getPwd());
return user;
} catch (DataAccessException e) {
e.printStackTrace();
}
return null;
}
}
-
编写cn.web.servlet.LoginServlet类 package cn.myweb.servlet;
import cn.domain.User;
import cn.op.UserOp;
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("/loginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
req.setCharacterEncoding("utf-8");
String u = req.getParameter("username");
String p = req.getParameter("password");
User logier = new User();
logier.setUsername(u);
logier.setPwd(p);
System.out.println(logier);
System.out.println("要进入");
UserOp op = new UserOp();
System.out.println("进入后");
User user = op.login(logier);
if(user==null){
req.getRequestDispatcher("/failServlet").forward(req,resp);
}else{
req.setAttribute("user",user);
req.getRequestDispatcher("/successServlet").forward(req,resp);
}
} catch (ServletException | IOException e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
-
login.html中form表单的action路径的写法
-
BeanUtils工具类,完成数据封装
-
用于封装JavaBean的
-
JavaBean:标准的java类
- 要求:
- 类必须被public修饰
- 必须提供空参的构造器
- 成员变量必须使用private修饰
- 提供公用setter和getter方法
- 功能:封装数据
-
概念:
- 成员变量:
- 属性:setter和getter方法截取后的产物
- 例如:getUsername() --> Username --> username
-
方法:
-
setProperty() -
getProperty() -
populate(Object obj,Map map):将map集合的键值对信息,封装到对应的JavaBean对象中 package cn.myweb.servlet;
import cn.domain.User;
import cn.op.UserOp;
import com.mchange.v2.beans.BeansUtils;
import com.mchange.v2.codegen.bean.BeangenUtils;
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("/loginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
req.setCharacterEncoding("utf-8");
Map<String, String[]> map = req.getParameterMap();
System.out.println("mima---"+map.get("password")[0]);;
User loginer = new User();
try {
BeanUtils.populate(loginer,map);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
System.out.println(loginer);
System.out.println("要进入");
UserOp op = new UserOp();
System.out.println("进入后");
User user = op.login(loginer);
if(user==null){
req.getRequestDispatcher("/failServlet").forward(req,resp);
}else{
req.setAttribute("user",user);
req.getRequestDispatcher("/successServlet").forward(req,resp);
}
} catch (ServletException | IOException e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
(“user”,user); //转发/重定向 req.getRequestDispatcher("/successServlet").forward(req,resp); } } catch (ServletException | IOException e) { e.printStackTrace(); }
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
```
|