HTTP 协议
什么是HTTP 协议
- 协议是指双方,或多方,相互约定好,大家都需要遵守的规则,叫协议。
- 所谓 HTTP 协议,就是指,客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫HTTP 协议。
- HTTP 协议中的数据又叫报文。
请求的HTTP 协议格式
- 客户端给服务器发送数据叫请求。
- 服务器给客户端回传数据叫响应。
- 请求又分为 GET 请求,和 POST 请求两种
GET 请求与 POST 请求
- GET 请求
- 请求行
- 请求的方式 GET
- 请求的资源路径 [+?+请求参数]
- 请求的协议版本号 HTTP/1.1
- 请求头
- key : value 组成不同的键值对,表示不同的含义。
http://localhost:8080/web01/hello?username=admin&password=123456
- key : value 组成不同的键值对,表示不同的含义。
- 请求行
- POST 请求
- 请求行
- 请求的方式 POST
- 请求的资源路径 [+?+请求参数]
- 请求的协议版本号 HTTP/1.1
- 请求头
- key : value 不同的请求头,有不同的含义
- 请求体:就是发送给服务器的数据
- 请求行
发送 POST 请求:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- /hello 前面的第一个 / 代表主机 localhost:8080-->
<form action="/hello" method="post">
用户名:<input type="text" name="username" id="username"><br/>
密码:<input type="password" name="password" id="password"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 注册servlet -->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>cn.lanqiao.HelloServlet</servlet-class>
<!-- 配置初始化时机,配置为0,则servlet随着容器的启动而完成构造和初始化-->
<!-- <load-on-startup></load-on-startup>-->
<init-param>
<param-name>username</param-name>
<param-value>admin</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>12345</param-value>
</init-param>
</servlet>
<!-- 配置servlet映射路径 -->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
如何区分 GET 请求与 POST 请求:
- GET 请求:
- form 标签method=get
- a 标签
- link 标签引入css
- Script 标签引入js 文件
- img 标签引入图片
- iframe 引入html 页面
- 在浏览器地址栏中输入地址后敲回车
- POST 请求有哪些:
- form 标签method=post
GET 请求与 POST 请求的区别
- GET 会产生一个 TCP 数据包
- 浏览器将 http header 与 date 一并发送出去
- POST 会产生两个 TCP 数据包
- 浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200
- POST 时间消耗较多,但在验证数据包完整性方面有优点
- 不是所有的浏览器都发送两次包
响应的 HTTP 协议格式
- 响应行
(1) 响应的协议和版本号
(2) 响应状态码
(3) 响应状态描述符 - 响应头
key : value 不同的响应头,有其不同含义 - 响应体: 就是回传给客户端的数据
- 常见的响应码说明:
- 200 表示请求成功
- 302 表示请求从定向
- 404 表示请求服务器已收到,但是所要的数据不存在(请求地址错误)
- 500 表示服务器已经收到请求,但是服务器内部错误(代码错误)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/app" method="post">
用户名:<input type="text" name="username" id="username"><br/>
密码:<input type="password" name="password" id="password"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 注册servlet -->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>cn.lanqiao.HelloServlet</servlet-class>
<!-- 配置初始化时机,配置为0,则servlet随着容器的启动而完成构造和初始化-->
<!-- <load-on-startup></load-on-startup>-->
<init-param>
<param-name>username</param-name>
<param-value>admin</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>12345</param-value>
</init-param>
</servlet>
<!-- 配置servlet映射路径 -->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>cn.lanqiao.AppServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app</url-pattern>
</servlet-mapping>
</web-app>
package cn.lanqiao;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class AppServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost 执行");
resp.sendRedirect("/success.html");
}
}
MINE(content-type)类型说明
-
MINE 是 HTTP 协议中的数据类型
-
MINE(Multipurpose Internet Mail Extensions) 多功能Internet 邮件扩充服务。MIME 类型的格式是“大类型/小类型”,并与某一种文件的扩展名相对应。
-
常见的 MINE 类型
文件 | MIME 类型 |
---|---|
超文本标记语言文本 | .html , .htm text/html |
普通文本 | .txt text/plain |
RTF 文本 | .rtf application/rtf |
GIF 图形 | .gif image/gif |
JPEG 图形 | .jpeg,.jpg image/jpeg |
au 声音文件 | .au audio/basic |
MIDI 音乐文件 | mid,.midi audio/midi,audio/x-midi |
RealAudio 音乐文件 | .ra, .ram audio/x-pn-realaudio |
MPEG 文件 | .mpg,.mpeg video/mpeg |
AVI 文件 | .avi video/x-msvideo |
GZIP 文件 | .gz application/x-gzip |
TAR 文件 | .tar application/x-tar |
HttpServletRequest 类
作用
响应客户端
每次只要有请求进入Tomcat 服务器,Tomcat 服务器就会把请求过来的HTTP 协议信息解析好封装到Request 对象中。
然后传递到service 方法(doGet 和doPost)中给我们使用。我们可以通过HttpServletRequest 对象,获取到所有请求的信息。
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class AppServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求头的 accept 信息
String accept = req.getHeader("Accept");
System.out.println("accept = " + accept);
//accept = text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
// 获取请求的 URI 定位路径
String uri = req.getRequestURI();
System.out.println("uri = " + uri); // uri = /app (主机之后的地址)
// 获取请求的上下文路径,对于整个 web 应用而言,值是一致的,也可以看作请求的时候的项目的路径
String contextPath = req.getContextPath();
System.out.println("contextPath = " + contextPath); // contextPath =
// 获取请求方式
String method = req.getMethod();
System.out.println("method = " + method); // method = POST
// 获取请求的网络地址
String url = req.getRequestURL().toString();
System.out.println("url = " + url); // url = http://localhost:8080/app
// 获取请求的 servlet 的 url-patern
String servletPath = req.getServletPath();
System.out.println("servletPath = " + servletPath); // servletPath = /app
}
}
通过 HttpServletRequest 获取请求的参数
通过地址栏获取(获取方式为 get):
Request URL: http://localhost:8080/app?username=admin&password=12345
Request Method: GET
public class AppServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 通过 req 获取请求参数,参数在传递的时候都是以键值对的形式存在的
String username = req.getParameter("username");
System.out.println("username = " + username);
String password = req.getParameter("password");
System.out.println("password = " + password);
String sex = req.getParameter("sex");
System.out.println("sex = " + sex);
// 获取多个爱好信息
String[] hobby = req.getParameterValues("hobby");
for (String h : hobby){
System.out.println("h = " + h);
}
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--只有表单能发送post请求-->
<form action="/app" method="post">
用户名:<input type="text" name="username" id="username"><br/>
密码:<input type="password" name="password" id="password"><br/>
性别:<input type="radio" name="sex" value="man">男
<input type="radio" name="sex" value="woman">女<br>
爱好:<input type="checkbox" name="hobby" value="bas">篮球
<input type="checkbox" name="hobby" value="sc">足球
<input type="checkbox" name="hobby" value="pp">乒乓球<br>
<input type="submit" value="提交">
</form>
</body>
</html>
username = amdin
password = admin
sex = woman
h = bas
h = sc
h = pp
当提交表单的时候,使用 req.getParameter 或者 req.getParameterValues 获取表单数据的时候,使用的是表单元素的 name 属性,因此在设计表单时,表单元素必须有 name 属性。
同时后台获取的数据都是其所对应的 values 属性的值。
通过 req.getParameter 或者 req.getParameterValues 得到的数据都是 String 类型
解决提交数据的中文乱码问题
GET 请求时,存在的中文乱码:
- 解决方案一:先按照 UTF-8 解码,再使用 UTF-8 编码
String name = new String(username.getBytes(StandardCharsets.UTF_8),"UTF-8");
String username = req.getParameter("username");
System.out.println("username = " + username);
String name = new String(username.getBytes(StandardCharsets.UTF_8),"UTF-8");
System.out.println("name = " + name);
- 解决方案二:修改 tomcat 的 servlet.xml
POST 请求的中文乱码:req.setCharacterEncoding(“UTF-8”); 必须写在所有获取参数之前
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决通过 post 请求的中文乱码,必须写在获取参数之前
req.setCharacterEncoding("UTF-8");
}
HttpServletResponse
作用
HttpServletResponse 类和 HttpServletRequest 一样。每次请求,Tomcat 服务器都会创建一个Response 对象传递给Servlet 程序去使用。
HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息,我们如果需要设置返回给客户端的信息,都可以通过HttpServletResponse 对象来进行设置
字节、字符输出流的说明
- 字节流 getOutputStream() :常用于下载(传递二进制数据)
- 字符流 getWriter() :常用于回传字符串(常用)
两种输出流只能同时使用一种。
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.write("username = " + username);
out.write("password = " + "<h1>" + password + "<h1/>");
out.write("sex = " + sex);
out.flush(); // 刷新数据
}
在网页上输出:
username = adminpassword = <h1>12345<h1/>sex = man
解决响应乱码问题(写在最前面):
- 解决方法一:
resp.setContentType("text/html; charset=UTF-8");
- 解决方法二(其实是方法一的分开形式):
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
- 解决方法三:
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
请求转发、重定向
- 请求转发是指:服务器收到请求后,从一个资源跳转到另一个资源的操作
//将请求传递给另一个servlet来处理 请求转发
req.getRequestDispatcher("/demo").forward(req,resp);
req.getRequestDispatcher("/success.html").forward(req,resp);
- 请求转发的特点:
- 地址栏的请求地址不变
- 请求转发只发送了一次请求
- 请求转发可以是 get 请求也可以是 post 请求
- 请求转发的目标:
- 另一个 servlet
- 另一个 html 页面
- 请求转发若转发到 servlet ,此时两个 servlet 的 request 对象是同一个对象
- 因此可以在两个 servlet 中共享请求数据
- 请求转发只能转发到当前应用的内部资源
AppServlet 中请求转发:
public class AppServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("APP Servlet 处理请求");
// 将请求传递给另一个 servlet 来处理
req.getRequestDispatcher("/demo").forward(req,resp);
}
}
web.xml 中进行配置:
public class ServletDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demoServlet 处理请求");
}
}
请求转发若转发到 servlet ,此时两个 servlet 的 request 对象是同一个对象 说明:
public class ServletDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demoServlet 处理请求");
String username = req.getParameter("username");
System.out.println("username = " + username);
String password = req.getParameter("password");
System.out.println("password = " + password);
}
}
ServletDemo 中也可以获取到表单的数据
Web 中的相对路径与绝对路径
- 相对路径是:
- . 表示当前目录
- … 表示上一级目录
- 资源名 表示当前目录/资源名
- 绝对路径:
- http://ip:port/工程路径/资源路径
在实际开发中,路径都使用绝对路径,而不简单的使用相对路径。
- http://ip:port/工程路径/资源路径
web 中 / 斜杠的不同意义:
- 在web 中, / 是一种绝对路径
- / 如果被服务器解析,得到的地址是: http://ip:post/
- / 如果被服务器解析,得到的地址是:http://ip:port/工程路径
- 特殊情况: response.sendRediect(“/”); 把斜杠发送给浏览器解析。得到http://ip:port/
base 的使用(只能在 jsp 文件中使用):
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<base href="http://localhost:8080/">
</head>
<body>
<!--只有表单能发送post请求-->
<form action="app" method="post">
用户名:<input type="text" name="username" id="username"><br/>
密码:<input type="password" name="password" id="password"><br/>
性别:<input type="radio" name="sex" value="man">男
<input type="radio" name="sex" value="woman">女<br>
爱好:<input type="checkbox" name="hobby" value="bas">篮球
<input type="checkbox" name="hobby" value="sc">足球
<input type="checkbox" name="hobby" value="pp">乒乓球<br>
<input type="submit" value="提交">
</form>
</body>
</html>
重定向
重定向:将当前的请求重新定向到一个新的请求地址
请求重定向是指客户端给服务器发送请求,然后服务器告诉客户端说,我给你一些地址,你去新地址访问,叫请求重定向(之前的地址可能已经被废弃)
//重定向 地址是最终给到了浏览器
resp.sendRedirect("/web01/demo");
- 重定向的时候,地址栏的地址发生了变化,最终呈现的是重定向之后的请求地址
- 重定向发送了两次请求,第一次可以是 get 也可是post 但是第二次请求一定是 get 请求
- 因为是两次请求,所以 req 的数据无法共享
- 重定向不仅可以重定向到内部资源(例如转发到我们写的 success.html 页面),也可以重定向到外部资源。
// 重定向
// 重定向到内部资源
resp.sendRedirect("success.html");
// 重定向到外部资源 resp.sendRedirect("http://www.baidu.com");
public class AppServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("APP Servlet 处理请求");
// 将请求传递给另一个 servlet 来处理
//req.getRequestDispatcher("/demo").forward(req,resp);
// 重定向
resp.sendRedirect("/demo");
}
}
重定向共发起了两次请求
JavaEE 项目的三层架构
分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。
web 层 | com.web.web/servlet/controller | |
---|---|---|
service 层 | com.web.service Service | 接口包 |
com.web.service.impl Service | 接口实现类 | |
dao持久层 | com.web.dao Dao | 接口包 |
com.web.dao.impl Dao | 接口实现类 | |
实体bean 对象 | com.web.pojo/entity/domain/bean | JavaBean 类 |
测试包 | com.web.test/junit | |
工具类 | com.web.utils |
创建工程引入静态资源
引入两个依赖:
tomcat目录中 lib中的 jsp-api.jar 和 servlet-api.jar
注:所有的 jar 包放在 WEB-INF 下
若还无法使用,再进行下述设置:
创建数据库及表
create table t_user(
id
int primary key auto_increment,
username
varchar(20) not null unique,
password
varchar(32) not null,
email
varchar(200)
);
insert into t_user(username
,password
,email
) values(‘admin’,‘admin’,‘admin@126.com’);
select * from t_user;
编写数据库表对应的 JavaBean 对象
写一个 User 类
public class User {
private Integer id;
private String username;
private String password;
private String email;
public User() {
}
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
public User(Integer id, String username, String password, String email) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
}
public Integer getId() {
return id;
}
public void setId(Integer 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;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
}
链接数据库
导包(jdbc druid dbutils)
jdbc.properties
username=root
password=root
url=jdbc:mysql://localhost:3306/book
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10
JDBC 工具类
public class JDBCUtils {
private static DruidDataSource dataSource;
static {
try {
Properties properties = new Properties();
// 读取jdbc.properties 属性配置文件
InputStream inputStream =
JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
// 从流中加载数据
properties.load(inputStream);
// 创建数据库连接池
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接池中的连接
* @return 如果返回null,说明获取连接失败<br/>有值就是获取连接成功
*/
public static Connection getConnection(){
Connection conn = null;
try {
conn = dataSource.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
/**
* 关闭连接,放回数据库连接池
* @param conn
*/
public static void close(Connection conn){
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
基于 DBUtils 结合泛型,创建一个 BaseDao
public abstract class BaseDAO {
//使用DbUtils 操作数据库
private QueryRunner queryRunner = new QueryRunner();
/**
* update() 方法用来执行:Insert\Update\Delete 语句
*
* @return 如果返回-1,说明执行失败<br/>返回其他表示影响的行数
*/
public int update(String sql, Object... args) {
Connection connection = JDBCUtils.getConnection();
try {
return queryRunner.update(connection, sql, args);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.close(connection);
}
return -1;
}
/**
* 查询返回一个javaBean 的sql 语句
*
* @param type 返回的对象类型
* @param sql 执行的sql 语句
* @param args sql 对应的参数值
* @param <T> 返回的类型的泛型
* @return
*/
public <T> T queryForOne(Class<T> type, String sql, Object... args) {
Connection con = JDBCUtils.getConnection();
try {
return queryRunner.query(con, sql, new BeanHandler<T>(type), args);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.close(con);
}
return null;
}
/**
* 查询返回多个javaBean 的sql 语句
*
* @param type 返回的对象类型
* @param sql 执行的sql 语句
* @param args sql 对应的参数值
* @param <T> 返回的类型的泛型
* @return
*/
public <T> List<T> queryForList(Class<T> type, String sql, Object... args) {
Connection con = JDBCUtils.getConnection();
try {
return queryRunner.query(con, sql, new BeanListHandler<T>(type), args);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.close(con);
}
return null;
}
/**
* 执行返回一行一列的sql 语句
* @param sql 执行的sql 语句
* @param args sql 对应的参数值
* @return
*/
public Object queryForSingleValue(String sql, Object... args){
Connection conn = JDBCUtils.getConnection();
try {
return queryRunner.query(conn, sql, new ScalarHandler(), args);
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtils.close(conn);
}
return null;
}
}
创建 UserDao 并完成测试
public interface IUserDao {
//新增用户 完成注册
int insert(User user);
// 完成登陆 根据用户名和密码查询用户是否存在
User selectUserByUsernameAndPassword(String username,String password);
// 用户名唯一 在注册时候 检测用户名是否被占用
User selectUserByUser(String username);
}
实现接口:
public class UserDaoImpl extends BaseDAO implements IUserDao {
@Override
public int insert(User user) {
String sql = "insert into t_user(username,password,email) values(?,?,?)";
return update(sql,user.getUsername(),user.getPassword(),user.getEmail());
}
@Override
public User selectUserByUsernameAndPassword(String username, String password) {
String sql = "select * from t_user where username=? and password=?";
return queryForOne(User.class,sql,username,password);
}
@Override
public User selectUserByUser(String username) {
String sql = "select * from t_user where username=? ";
return queryForOne(User.class,sql,username);
}
}
测试:
public class UserDAOTest {
private IUserDao userDao ;
@BeforeEach
public void init(){
userDao = new UserDaoImpl();
}
@Test
public void insertTest(){
User user = new User("tom","123466","tom@126.com");
userDao.insert(user);
}
@Test
public void selectUserTest(){
User user = userDao.selectUserByUser("tom");
System.out.println("user = " + user);
}
}
Service 层
Service接口:
public interface IUserService {
//保存用户
int save(User user);
//登陆
User login(String username,String password);
//检查用户名是否被占用
User checkUsername(String username);
}
Service 的实现:
public class UserService implements IUserService {
private IUserDao userDao = new UserDaoImpl();
@Override
public int save(User user) {
return userDao.insert(user);
}
@Override
public User login(String username, String password) {
return userDao.selectUserByUsernameAndPassword(username,password);
}
@Override
public User checkUsername(String username) {
return userDao.selectUserByUser(username);
}
}
Web 层
controller 是 servlet 处理浏览器发送的请求,并给出响应
public class LoginController extends HttpServlet {
private IUserService userService = new UserServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 接收用户输入的用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
User user = userService.login(username,password);
System.out.println("user = " + user);
if(user!=null){
req.getRequestDispatcher("/pages/user/login_success.html").forward(req,resp);
}else{
resp.sendRedirect("/pages/user/login.html");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>cn.lanqiao.book.controller.LoginController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
Login.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>零点读书会员登录页面</title>
<link type="text/css" rel="stylesheet" href="../../static/css/style.css" >
<base href="http://localhost:8080/book/">
</head>
<body>
<div id="login_header">
</div>
<div class="login_banner">
<div id="l_content">
<img class="login_img" alt="" src="../../static/img/logo.jpg" >
</div>
<div id="content">
<div class="login_form">
<div class="login_box">
<div class="tit">
<h1>零点会员</h1>
<a href="regist.html">立即注册</a>
</div>
<div class="msg_cont">
<b></b>
<span class="errorMsg">请输入用户名和密码</span>
</div>
<div class="form">
<form action="login" method="post">
<label>用户名称:</label>
<input class="itxt" type="text" placeholder="请输入用户名" autocomplete="off" tabindex="1" name="username" />
<br />
<br />
<label>用户密码:</label>
<input class="itxt" type="password" placeholder="请输入密码" autocomplete="off" tabindex="1" name="password" />
<br />
<br />
<input type="submit" value="登录" id="sub_btn" />
</form>
</div>
</div>
</div>
</div>
</div>
<div id="bottom">
<span>
零点读书.Copyright ©2020
</span>
</div>
</body>
</html>
注册
controller 文件
public class RegistController extends HttpServlet {
private IUserService userService = new UserServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username= req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
User user = new User(username,password,email);
userService.save(user);
req.getRequestDispatcher("/pages/user/regist_success.html").forward(req,resp);
}
}
web.html 中添加:
<servlet>
<servlet-name>regist</servlet-name>
<servlet-class>cn.lanqiao.book.controller.RegistController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>regist</servlet-name>
<url-pattern>/regist</url-pattern>
</servlet-mapping>
注册页面(html 文件):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>零点读书会员注册页面</title>
<base href="http://localhost:8080/book/">
<link type="text/css" rel="stylesheet" href="static/css/style.css" >
<style type="text/css">
.login_form{
height:420px;
margin-top: 25px;
}
</style>
<script type="text/javascript" src="../../static/js/jquery-1.12.4.js"></script>
<script type="text/javascript">
// 页面加载完成之后
$(function () {
// 给注册绑定单击事件
$("#sub_btn").click(function () {
// 验证用户名: 必须由字母, 数字下划线组成, 并且长度为 5 到 12 位
//1 获取用户名输入框里的内容
var usernameText = $("#username").val();
//2 创建正则表达式对象
var usernamePatt = /^\w{5,12}$/;
//3 使用 test 方法验证
if (!usernamePatt.test(usernameText)) {
//4 提示用户结果
$("span.errorMsg").text("用户名不合法! ");
return false;
}
//验证密码: 必须由字母, 数字下划线组成, 并且长度为 5 到 12 位
//1 获取用户名输入框里的内容
var passwordText = $("#password").val();
//2 创建正则表达式对象
var passwordPatt = /^\w{5,12}$/;
//3 使用 test 方法验证
if (!passwordPatt.test(passwordText)) {
//4 提示用户结果
$("span.errorMsg").text("密码不合法! ");
return false;
}
//验证确认密码: 和密码相同
//1 获取确认密码内容
var repwdText = $("#repwd").val();
//2 和密码相比较
if (repwdText != passwordText) {
//3 提示用户
$("span.errorMsg").text("确认密码和密码不一致! ");
return false;
}
//邮箱验证: xxxxx@xxx.com
//1 获取邮箱里的内容
var emailText = $("#email").val();
//2 创建正则表达式对象
var emailPatt = /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/;
//3 使用 test 方法验证是否合法
if (!emailPatt.test(emailText)) {
//4 提示用户
$("span.errorMsg").text("邮箱格式不合法! ");
return false;
}
//验证码: 现在只需要验证用户已输入。 因为还没讲到服务器。 验证码生成。
var codeText = $("#code").val();
//去掉验证码前后空格
alert("去空格前: ["+codeText+"]")
codeText = $.trim(codeText);
alert("去空格后: ["+codeText+"]")
if (codeText == null || codeText == "") {
//4 提示用户
$("span.errorMsg").text("验证码不能为空! ");
return false;
}
$("span.errorMsg").text("");
});
});
</script>
</head>
<body>
<div id="login_header">
<img class="login_img" alt="" src="static/img/logo.jpg" >
</div>
<div class="login_banner">
<div id="l_content">
<span class="login_word">欢迎注册</span>
</div>
<div id="content">
<div class="login_form">
<div class="login_box">
<div class="tit">
<h1>注册零点读书会员</h1>
<span class="errorMsg"></span>
</div>
<div class="form">
<form action="regist" method="post">
<label>用户名称:</label>
<input class="itxt" type="text" placeholder="请输入用户名" autocomplete="off" tabindex="1" name="username" id="username" />
<br />
<br />
<label>用户密码:</label>
<input class="itxt" type="password" placeholder="请输入密码" autocomplete="off" tabindex="1" name="password" id="password" />
<br />
<br />
<label>确认密码:</label>
<input class="itxt" type="password" placeholder="确认密码" autocomplete="off" tabindex="1" name="repwd" id="repwd" />
<br />
<br />
<label>电子邮件:</label>
<input class="itxt" type="text" placeholder="请输入邮箱地址" autocomplete="off" tabindex="1" name="email" id="email" />
<br />
<br />
<label>验证码:</label>
<input class="itxt" type="text" style="width: 150px;" id="code"/>
<img alt="" src="static/img/code.bmp" style="float: right; margin-right: 40px">
<br />
<br />
<input type="submit" value="注册" id="sub_btn" />
</form>
</div>
</div>
</div>
</div>
</div>
<div id="bottom">
<span>
零点读书.Copyright ©2020
</span>
</div>
</body>
</html>