1.1 用户登录
1.1.1 需求分析
- 用户在登录页面输入用户名和密码,提交请求给
LoginServlet
- 在
LoginServlet
中接收请求和数据[用户名和密码] - 在
LoginServlt
中通过Mybatis
实现调用UserMapper
来根据用户名和密码查询数据库表 - 将查询的结果封装到
User
对象中进行返回 - 在
LoginServlet
中判断返回的User
对象是否为null
- 如果为
nul
,说明根据用户名和密码没有查询到用户,则登录失败,返回"登录失败"数据给前端 - 如果不为
null
,则说明用户存在并且密码正确,则登录成功,返回"登录成功"数据给前端
1.1.2 环境准备
- 复制静态页面到项目的
webapp
目录下,效果如下:
- 创建db1数据库,创建tb_user表,创建User实体类
2.1 将sql语句执行下:
2.2 创建User.java
实体类
package com.dcxuexi.pojo;
/***
* @Title User
* @Description TOTD
* @Auter DongChuang
* @Date 2023/1/1 16:33
* @Version 1.0.0
*/
public class User {
private Integer id;
private String username;
private String password;
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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
- 在项目的
pom.xml
导入Mybatis
和Mysql
驱动坐标
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
- 创建
mybatis-config.xml
核心配置文件,UserMapper.xml
映射文件,UserMapper
接口
4.1 在resources
目录下创建mybatis-config.xml
配置文件
<?xml version="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>
<package name="com.dcxuexi.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--
useSSL:关闭SSL安全连接 性能更高
useServerPrepStmts:开启预编译功能
& 等同于 & ,xml配置文件中不能直接写 &符号
-->
<property name="url" value="jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--扫描mapper-->
<package name="com.dcxuexi.mapper"/>
</mappers>
</configuration>
4.2 在com.dcxuexi.mapper
包下创建UserMapper
接口
package com.dcxuexi.mapper;
/***
* @Title UserMapper
* @Description TOTD
* @Auter DongChuang
* @Date 2023/1/1 16:45
* @Version 1.0.0
*/
public interface UserMapper {
}
4.3 resources
目录下创建UserMapper.xml
注意:在resources
下创建UserMapper.xml
的目录时,要使用/
分割
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dcxuexi.mapper.UserMapper">
</mapper>
至此我们所需要的环境就都已经准备好了,具体该如何实现?
1.1.3 代码实现
- 在
UserMapper
接口中提供一个根据用户名和密码查询用户对象的方法
package com.dcxuexi.mapper;
import com.dcxuexi.pojo.User;
import org.apache.ibatis.annotations.Param;
/***
* @Title UserMapper
* @Description TOTD
* @Auter DongChuang
* @Date 2023/1/1 16:45
* @Version 1.0.0
*/
public interface UserMapper {
/**
* 根据用户名和密码查询用户对象
* @param username
* @param password
* @return
*/
User select(@Param("username") String username, @Param("password") String password);
}
UserMapper.xml
实现根据用户名和密码查询用户对象。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dcxuexi.mapper.UserMapper">
<select id="select" resultType="com.dcxuexi.pojo.User">
select * from tb_user
where username = #{username}
and password = #{password}
</select>
</mapper>
说明
@Param
注解的作用:用于传递参数,是方法的参数可以与SQL
中的字段名相对应。
- 修改
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
<link href="css/login.css" rel="stylesheet">
</head>
<body>
<div id="loginDiv">
<form action="/request_demo/loginServlet" method="post" id="form">
<h1 id="loginMsg">LOGIN IN</h1>
<p>Username:<input id="username" name="username" type="text"></p>
<p>Password:<input id="password" name="password" type="password"></p>
<div id="subDiv">
<input type="submit" class="button" value="login up">
<input type="reset" class="button" value="reset">
<a href="register.html">没有账号?点击注册</a>
</div>
</form>
</div>
</body>
</html>
- 编写
LoginServlet
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//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);
}
}
- 启动服务器测试
4.1 如果用户名和密码输入错误,则
4.2 如果用户名和密码输入正确,则
至此用户的登录功能就已经完成了。
1.2 用户注册
1.2.1 需求分析
- 用户在注册页面输入用户名和密码,提交请求给
RegisterServlet
- 在
RegisterServlet
中接收请求和数据[用户名和密码] - 在
RegisterServlet
中通过Mybatis
实现调用UserMapper
来根据用户名查询数据库表 - 将查询的结果封装到
User
对象中进行返回 - 在
RegisterServlet
中判断返回的User
对象是否为null
- 如果为
nul
,说明根据用户名可用,则调用UserMapper
来实现添加用户 - 如果不为
null
,则说明用户不可以,返回"用户名已存在"数据给前端
1.2.2 代码编写
-
编写UserMapper提供根据用户名查询用户数据方法和添加用户方法
package com.dcxuexi.mapper; import com.dcxuexi.pojo.User; import org.apache.ibatis.annotations.Param; /*** * @Title UserMapper * @Description TOTD * @Auter DongChuang * @Date 2023/1/1 16:45 * @Version 1.0.0 */ public interface UserMapper { /** * 根据用户名和密码查询用户对象 * @param username * @param password * @return */ User select(@Param("username") String username, @Param("password") String password); /** * 根据用户名查询用户对象 * @param username * @return */ User selectByUsername(String username); /** * 添加用户 * @param user */ void add(User user); }
UserMapper.xml
实现方法
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dcxuexi.mapper.UserMapper">
<select id="select" resultType="com.dcxuexi.pojo.User">
select * from tb_user
where username = #{username}
and password = #{password}
</select>
<select id="selectByUsername" resultType="com.dcxuexi.pojo.User">
select * from tb_user
where username = #{username}
</select>
<insert id="add">
insert into tb_user
values(null,#{username},#{password})
</insert>
</mapper>
- 修改
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎注册</title>
<link href="css/register.css" rel="stylesheet">
</head>
<body>
<div class="form-div">
<div class="reg-content">
<h1>欢迎注册</h1>
<span>已有帐号?</span> <a href="login.html">登录</a>
</div>
<form id="reg-form" action="/request_demo/registerServlet" method="post">
<table>
<tr>
<td>用户名</td>
<td class="inputs">
<input name="username" type="text" id="username">
<br>
<span id="username_err" class="err_msg" style="display: none">用户名不太受欢迎</span>
</td>
</tr>
<tr>
<td>密码</td>
<td class="inputs">
<input name="password" type="password" id="password">
<br>
<span id="password_err" class="err_msg" style="display: none">密码格式有误</span>
</td>
</tr>
</table>
<div class="buttons">
<input value="注 册" type="submit" id="reg_btn">
</div>
<br class="clear">
</form>
</div>
</body>
</html>
- 创建
RegisterServlet
类
package com.dcxuexi.web;
import com.dcxuexi.mapper.UserMapper;
import com.dcxuexi.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
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.io.InputStream;
/***
* @Title RegisterServlet
* @Description TOTD
* @Auter DongChuang
* @Date 2023/1/1 17:47
* @Version 1.0.0
*/
@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 接收用户数据
String username = req.getParameter("username");
String password = req.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 user2 = userMapper.selectByUsername(username);
resp.setContentType("text/html;charset=utf-8");
//3. 判断用户对象释放为null
if (user2 == null){
// 用户名不存在,添加用户
userMapper.add(user);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
resp.getWriter().write("用户注册成功");
}else {
// 用户名存在,给出提示信息
resp.getWriter().write("用户名已存在");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
- 启动服务器进行测试
4.1 如果测试成功,则在数据库中就能查看到新注册的数据
4.2 如果用户已经存在,则在页面上展示 用户名已存在
的提示信息
1.3 SqlSessionFactory
工具类抽取
上面两个功能已经实现,但是在写Servlet
的时候,因为需要使用Mybatis
来完成数据库的操作,所以对于Mybatis
的基础操作就出现了些重复代码,如下
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
有了这些重复代码就会造成一些问题:
- 重复代码不利于后期的维护
SqlSessionFactory
工厂类进行重复创建- 就相当于每次买手机都需要重新创建一个手机生产工厂来给你制造一个手机一样,资源消耗非常大但性能却非常低。所以这么做是不允许的。
那如何来优化呢?
- 代码重复可以抽取工具类
- 对指定代码只需要执行一次可以使用静态代码块
有了这两个方向后,代码具体该如何编写?
package com.dcxuexi.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
/***
* @Title SqlSessionFactoryUtils
* @Description TOTD
* @Auter DongChuang
* @Date 2023/1/1 18:05
* @Version 1.0.0
*/
public class SqlSessionFactoryUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
//静态代码块会随着类的加载而自动执行,且只执行一次
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}
工具类抽取以后,以后在对Mybatis
的SqlSession
进行操作的时候,就可以直接使用
SqlSessionFactory sqlSessionFactory =SqlSessionFactoryUtils.getSqlSessionFactory();
这样就可以很好的解决上面所说的代码重复和重复创建工厂导致性能低的问题了。
LoginServlet
类优化如下:
package com.dcxuexi.web;
import com.dcxuexi.mapper.UserMapper;
import com.dcxuexi.pojo.User;
import com.dcxuexi.util.SqlSessionFactoryUtils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
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.io.InputStream;
import java.io.PrintWriter;
/***
* @Title LoginServlet
* @Description TOTD
* @Auter DongChuang
* @Date 2023/1/1 17:02
* @Version 1.0.0
*/
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 接收用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("username = " + username);
//2. 调用MyBatis完成查询
//2.1 获取SqlSessionFactory对象
//String resource = "mybatis-config.xml";
//InputStream inputStream = Resources.getResourceAsStream(resource);
//SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
//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
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
if (user!=null){
// 登陆成功
writer.write(username+"登陆成功");
}else {
// 登陆失败
writer.write("登陆失败");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
RegisterServlet
类优化如下:
package com.dcxuexi.web;
import com.dcxuexi.mapper.UserMapper;
import com.dcxuexi.pojo.User;
import com.dcxuexi.util.SqlSessionFactoryUtils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
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.io.InputStream;
/***
* @Title RegisterServlet
* @Description TOTD
* @Auter DongChuang
* @Date 2023/1/1 17:47
* @Version 1.0.0
*/
@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 接收用户数据
String username = req.getParameter("username");
String password = req.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);
SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
//2.2 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//2.3 获取Mapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//2.4 调用方法
User user2 = userMapper.selectByUsername(username);
resp.setContentType("text/html;charset=utf-8");
//3. 判断用户对象释放为null
if (user2 == null){
// 用户名不存在,添加用户
userMapper.add(user);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
resp.getWriter().write("用户注册成功");
}else {
// 用户名存在,给出提示信息
resp.getWriter().write("用户名已存在");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}