概述
- Servlet 方法介绍
- Servlet urlPattern 配置
- IDEA 模板创建 Servlet
- 中文乱码问题
- POST 乱码
- GET 乱码
- 路径问题
- Response 响应字符数据
- Response 响应字节数据
- 用户登录案例
- 准备工作
- 流程
- 用户注册案例
- 代码优化
- 案例
- 准备工作
- 业务 - 查询所有
- 业务 - 添加
- 业务 - 修改(数据回显)
- 业务 - 修改(修改数据)
- 业务 - 删除
- 业务 - 用户登录
- 业务 - 记住用户
- 业务 - 注册
- 业务 - 注册验证码
- 业务 - 登录验证
Servlet 方法介绍
init()
:初始化方法- 调用时机:默认情况下,servlet 被第一次访问时,调用
- 可通过
loadOnStartup
修改
- 可通过
- 调用次数:1次
- 调用时机:默认情况下,servlet 被第一次访问时,调用
service()
:提供服务- 调用时机:每一次Servlet被访问时,调用
- 调用次数:多次
destory()
:销毁方法- 调用时机:内存释放或者服务器关闭的时候,Servlet对象会被销毁,调用
- 调用次数:1次
getServletConfig()
:获取 ServletConfig 对象getServletInfo()
:获取 Servlet 信息(author、version、copyright)
Servlet urlPattern 配置
- 一个 Servlet 可以配置多个 urlPattern
@WebServlet(urlPatterns = {"/demo3", "/demo4"})
- urlPattern 配置规则
- 精确匹配
- 配置路径:
@WebServlet("/demo3")
- 访问路径:
localhost:8080/web-demo/demo3
- 配置路径:
- 目录匹配
- 配置路径:
@WebServlet("/user/*")
- 访问路径:
localhost:8080/web-demo/user/aaa
、localhost:8080/web-demo/user/bbb
- 配置路径:
- 扩展名匹配
- 配置路径:
@WebServlet("*.do")
- 访问路径:
localhost:8080/web-demo/aaa.do
、localhost:8080/web-demo/bbb.do
- 配置路径:
- 任意匹配
- 配置路径:
@WebServlet("/")
、@WebServlet("/*")
- 访问路径:
localhost:8080/web-demo/hehe
、localhost:8080/web-demo/haha
- 配置路径:
- 精确匹配
/
和/*
的区别
- 当我们的项目中的Servlet配置了
/
,会覆盖掉 tomcat 中的 DefaultServlet,当其他的 url-pattern 都匹配不上时都会走这个Servlet- 当我们的项目中配置了
/*
,意味着匹配任意访问路径
优先级:精确路径 > 目录路径 > 扩展名路径 > /* > /
IDEA 模板创建 Servlet
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
#if ($JAVAEE_TYPE == "jakarta")
import jakarta.servlet.*;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;
#else
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
#end
import java.io.IOException;
@WebServlet("/${Entity_Name}")
public class ${Class_Name} extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
中文乱码问题
POST 乱码
getReader()
默认编码是iso-8859-1
- 设置字符输入流的编码为
UTF-8
:request.setCharacterEncoding("UTF-8");
GET 乱码
-
URL 编码
- 将字符串按照编码方式转为二进制
- 每个字节转为2个16进制并在前边加上%
-
URL编解码Demo
package com.ruochen.web; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; public class URLDemo { public static void main(String[] args) throws UnsupportedEncodingException { String username = "张三"; // 1. URL 编码 String encode = URLEncoder.encode(username, "utf-8"); System.out.println(encode); // 2. URL 解码 String decode = URLDecoder.decode(encode, "ISO-8859-1"); System.out.println(decode); } }
%E5%BC%A0%E4%B8%89 å¼ ä¸‰
-
tomcat ISO-8859-1 接码我们无法改变,但是我们可以发现 URL 编码数据和接收打的数据字节是一样的(二进制数据 10101xxxx),这就为我们提供了一种思路:我们可以将乱码的数据转换为字节数据(二进制数据),再将二进制字节数据转换为字符串,demo 如下
package com.ruochen.web; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; public class URLDemo { public static void main(String[] args) throws UnsupportedEncodingException { String username = "张三"; // 1. URL 编码 String encode = URLEncoder.encode(username, "utf-8"); System.out.println(encode); // 2. URL 解码 String decode = URLDecoder.decode(encode, "ISO-8859-1"); System.out.println(decode); // 3. 转换为字节数据,编码 byte[] bytes = decode.getBytes("ISO-8859-1"); for (byte b : bytes) { System.out.print(b + " "); } System.out.println(); // 4. 将字节数组转换为字符串,解码 String string = new String(bytes, "utf-8"); System.out.println(string); } }
%E5%BC%A0%E4%B8%89 å¼ ä¸‰ -27 -68 -96 -28 -72 -119 张三
-
servlet demo
@WebServlet("/req1") public class RequestDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 解决post乱码 getReader() 默认编码是 iso-8859-1 request.setCharacterEncoding("UTF-8"); // 设置字符输入流的编码 String username = request.getParameter("username"); System.out.println("解决乱码前:" + username); // GET 获取参数的方式:getQueryString() // 乱码原因:tomcat 进行URL解码,默认的字符集ISO-8859-1 // 1. 先对乱码进行编码,转为字节数组 // byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1); // 2. 字节数组解码 // username = new String(bytes, StandardCharsets.UTF_8); username = new String(username.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); System.out.println("解决乱码后:" + username); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
Tomcat 8 之后,已将GET请求乱码问题解决,设置默认的解码方式为 UTF-8
路径问题
- 明确路径谁使用?
- 浏览器使用:需要加虚拟目录(项目访问路径)
- 服务端使用:不需要加虚拟目录
- 练习
- <a href = “路径”>:加虚拟目录
- <form action=“路径”>:加虚拟目录
- req.getRequestDispatcher(“路径”):不需要加虚拟目录
- resp.sendRedirect(“路径”):需要加虚拟目录
Response 响应字符数据
- 使用 Response 对象获取字符输出流:
PrintWriter writer = resp.getWriter();
- 写数据:
write.write("aaa");
- 可通过设置 header 指定类型:
resp.setHeader("content-type", "text/html");
- 流不需要关闭,resp 对象销毁的时候会自动关闭
- 中文乱码,设置流的编码:
resp.setContentType("text/html;charset=utf-8");
Response 响应字节数据
- 通过 Response 对象获取字节输出流:
ServletOutputStream outputStream = resp.getOutputStream();
- 写数据:
outputStream.write(字节数据);
- 案例
package com.ruochen.web; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.FileInputStream; import java.io.IOException; @WebServlet("/resp1") public class ResponseDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 读取文件 FileInputStream fis = new FileInputStream("C:\Users\ruochen\Desktop\离雨.jpg"); // 2. 获取 response 字节输出流 ServletOutputStream os = response.getOutputStream(); // 3. 完成流的 copy byte[] buff = new byte[1024]; int len = 0; while((len = fis.read(buff)) != -1) { os.write(buff, 0, len); } fis.close(); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
- 我们可以使用
commons-io
工具类简化上述操作 - 导入坐标:
pom.xml
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency>
- 上述循环遍历代码可简化为如下
IOUtils.copy(fis, os);
用户登录案例
准备工作
login.html
放到 webapp 目录下<!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="/web-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>
login.css
* { margin: 0; padding: 0; } html { height: 100%; width: 100%; overflow: hidden; margin: 0; padding: 0; background: url(../imgs/Desert.jpg) no-repeat 0px 0px; background-repeat: no-repeat; background-size: 100% 100%; -moz-background-size: 100% 100%; } body { display: flex; align-items: center; justify-content: center; height: 100%; } #loginDiv { width: 37%; display: flex; justify-content: center; align-items: center; height: 300px; background-color: rgba(75, 81, 95, 0.3); box-shadow: 7px 7px 17px rgba(52, 56, 66, 0.5); border-radius: 5px; } #name_trip { margin-left: 50px; color: red; } p { margin-top: 30px; margin-left: 20px; color: azure; } input { margin-left: 15px; border-radius: 5px; border-style: hidden; height: 30px; width: 140px; background-color: rgba(216, 191, 216, 0.5); outline: none; color: #f0edf3; padding-left: 10px; } #username{ width: 200px; } #password{ width: 202px; } .button { border-color: cornsilk; background-color: rgba(100, 149, 237, .7); color: aliceblue; border-style: hidden; border-radius: 5px; width: 100px; height: 31px; font-size: 16px; } #subDiv { text-align: center; margin-top: 30px; } #loginMsg{ text-align: center;color: aliceblue; }
- 创建
db1
数据库,创建tb_user
表,创建User
实体类-- 创建数据库 create database db1 character set utf8; use db1; -- 创建用户表 CREATE TABLE tb_user( id int primary key auto_increment, username varchar(20) unique, password varchar(32) ); -- 添加数据 INSERT INTO tb_user(username,password) values('zhangsan','123'),('lisi','234'); SELECT * FROM tb_user;
package com.ruochen.pojo; 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 + ''' + '}'; } }
- 导入MyBatis 坐标,MySQL 驱动坐标
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</version> </dependency>
- 创建
mybatis-config.xml
核心配置文件,UserMapper.xml
映射文件,UserMapper
接口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.ruochen.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true"/> <property name="username" value="root"/> <property name="password" value="ruochen666"/> </dataSource> </environment> </environments> <mappers> <!--扫描mapper--> <package name="com.ruochen.mapper"/> </mappers> </configuration>
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.ruochen.mapper.UserMapper"> </mapper>
UserMapper.java
package com.ruochen.mapper; public interface UserMapper { }
- 目录树如下
流程
UserMapper.java
package com.ruochen.mapper; import com.ruochen.pojo.User; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; public interface UserMapper { /** * 根据用户名和密码查询用户对象 * @param username * @param password * @return */ @Select("select * from tb_user where username= #{username} and password = #{password}") User select(@Param("username") String username, @Param("password") String password); }
UserServlet.java
package com.ruochen.web; import com.ruochen.mapper.UserMapper; import com.ruochen.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.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; @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); } }
用户注册案例
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="#" method="get"> <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>
UserMapper.java
/** * 根据用户名查询用户对象 * @param username * @return */ @Select("select * from tb_user where username = #{username}") User selectByUserName(String username); /** * 添加用户 * @param user */ @Insert("insert into tb_user values (null, #{username}, #{password});") void add(User user);
- RegisterServlet
package com.ruochen.web; import com.ruochen.mapper.UserMapper; import com.ruochen.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.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; import java.io.InputStream; @WebServlet("/registerServlet") public class RegisterServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 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 u = userMapper.selectByUserName(username); // 3. 判断用户对象是否为 null if (u == null) { // 用户名不存在,添加用户 userMapper.add(user); // 提交事务 sqlSession.commit(); } else { // 用户名存在,给出提示信息 response.setContentType("text/html;charset=utf-8"); response.getWriter().write("用户名已存在"); } // 释放资源 sqlSession.close(); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
代码优化
- 创建 SqlSessionFactory 代码优化
- 代码重复:工具类
- SqlSessionFacroty 工厂只创建一次,不要重复创建:静态代码块
package com.ruochen.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; 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; } }
案例
准备工作
- 创建新的模块
brand_demo
,引入坐标
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.ruochen</groupId> <artifactId>brand-demo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</version> </dependency> <!--servlet--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!--jsp--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <!--jstl--> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--standard--> <!--jstl 1.2 版本不需要此依赖--> <!-- <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> --> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.1</version> </plugin> </plugins> </build> </project>
- 创建三层架构的包结构
- 数据库表
tb_brand
-- 创建数据库 create database db1 character set utf8; use db1; -- 删除tb_brand表 drop table if exists tb_brand; -- 创建tb_brand表 create table tb_brand ( -- id 主键 id int primary key auto_increment, -- 品牌名称 brand_name varchar(20), -- 企业名称 company_name varchar(20), -- 排序字段 ordered int, -- 描述信息 description varchar(100), -- 状态:0:禁用 1:启用 status int ); -- 添加数据 insert into tb_brand (brand_name, company_name, ordered, description, status) values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0), ('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1), ('小米', '小米科技有限公司', 50, 'are you ok', 1); SELECT * FROM tb_brand;
- 实体类
Brand
package com.ruochen.pojo; /** * 品牌实体类 */ public class Brand { // id 主键 private Integer id; // 品牌名称 private String brandName; // 企业名称 private String companyName; // 排序字段 private Integer ordered; // 描述信息 private String description; // 状态:0:禁用 1:启用 private Integer status; public Brand() { } public Brand(Integer id, String brandName, String companyName, String description) { this.id = id; this.brandName = brandName; this.companyName = companyName; this.description = description; } public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) { this.id = id; this.brandName = brandName; this.companyName = companyName; this.ordered = ordered; this.description = description; this.status = status; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getBrandName() { return brandName; } public void setBrandName(String brandName) { this.brandName = brandName; } public String getCompanyName() { return companyName; } public void setCompanyName(String companyName) { this.companyName = companyName; } public Integer getOrdered() { return ordered; } public void setOrdered(Integer ordered) { this.ordered = ordered; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } @Override public String toString() { return "Brand{" + "id=" + id + ", brandName='" + brandName + ''' + ", companyName='" + companyName + ''' + ", ordered=" + ordered + ", description='" + description + ''' + ", status=" + status + '}'; } }
- MyBatis 基础环境
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.ruochen.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="ruochen666"/> </dataSource> </environment> </environments> <mappers> <!--扫描mapper--> <package name="com.ruochen.mapper"/> </mappers> </configuration>
BrandMapper.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.ruochen.mapper.BrandMapper"> </mapper>
BrandMapper
接口
package com.ruochen.mapper; public interface BrandMapper { }
- 目录树如下
业务 - 查询所有
- Dao 层:
BrandMapper
/** * 查询所有 * @return */ @Select("select * from tb_brand") @ResultMap("brandResultMap") List<Brand> selectAll();
BrandMapper.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.ruochen.mapper.BrandMapper"> <resultMap id="brandResultMap" type="brand"> <result column="brand_name" property="brandName"></result> <result column="company_name" property="companyName"></result> </resultMap> </mapper>
- 工具类:
SqlSessionFactoryUtils
package com.ruochen.utils; 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; 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; } }
- Service 层:
BrandService
package com.ruochen.service; import com.ruochen.mapper.BrandMapper; import com.ruochen.pojo.Brand; import com.ruochen.utils.SqlSessionFactoryUtils; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import java.util.List; public class BrandService { // 1. 获取 sqlSessionFactory SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory(); /** * 查询所有功能 * @return */ public List<Brand> selectAll() { // 调用BrandMapper.selectAll() // 2. 获取 SqlSession SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 List<Brand> brands = mapper.selectAll(); // 5. 释放资源 sqlSession.close(); return brands; } }
- Web 层
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <a href="/brand-demo/selectAllServlet">查询所有</a> </body> </html>
SelectAllServlet
package com.ruochen.web; import com.ruochen.pojo.Brand; import com.ruochen.service.BrandService; 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.util.List; @WebServlet("/selectAllServlet") public class SelectAllServlet extends HttpServlet { private BrandService brandService = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 调用 BrandService 完成查询 List<Brand> brands = brandService.selectAll(); // 2. 存入request域中 request.setAttribute("brand", brands); // 3. 转发到 brand.jsp request.getRequestDispatcher("/brand.jsp").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
brand.jsp
<%-- Created by IntelliJ IDEA. User: ruochen Date: 2022/2/27 Time: 12:33 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>Title</title> </head> <body> <input type="button" value="新增"><br> <hr> <table border="1" cellspacing="0" width="80%"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <c:forEach items="${brands}" var="brand" varStatus="status"> <tr align="center"> <td>${status.count}</td> <td>${brand.brandName}</td> <td>${brand.companyName}</td> <td>${brand.ordered}</td> <td>${brand.description}</td> <c:if test="${brand.status == 1}"> <td>启用</td> </c:if> <c:if test="${brand.status != 1}"> <td>禁用</td> </c:if> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> </c:forEach> </table> </body> </html>
- 测试
注意点:resultMap 的使用:属性名称和数据库字段名称不一致
业务 - 添加
- Dao 层:
BrandMapper
@Insert("insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status});") void add(Brand brand);
- Service 层:
BrandService
/** * 添加 * @param brand */ public void add(Brand brand) { // 2. 获取 SqlSession SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 mapper.add(brand); // 提交事务 sqlSession.commit(); // 释放资源 sqlSession.close(); }
- Web 层:
brand.jsp
<%-- Created by IntelliJ IDEA. User: ruochen Date: 2022/2/27 Time: 12:33 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>Title</title> </head> <body> <input type="button" value="新增" id="add"><br> <hr> <table border="1" cellspacing="0" width="80%"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <c:forEach items="${brands}" var="brand" varStatus="status"> <tr align="center"> <td>${status.count}</td> <td>${brand.brandName}</td> <td>${brand.companyName}</td> <td>${brand.ordered}</td> <td>${brand.description}</td> <c:if test="${brand.status == 1}"> <td>启用</td> </c:if> <c:if test="${brand.status != 1}"> <td>禁用</td> </c:if> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> </c:forEach> </table> </body> <script> document.getElementById("add").onclick = function () { location.href = "/brand-demo/addBrand.jsp"; } </script> </html>
addBrand.jsp
<%-- Created by IntelliJ IDEA. User: ruochen Date: 2022/2/27 Time: 13:32 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta charset="UTF-8"> <title>添加品牌</title> </head> <body> <h3>添加品牌</h3> <form action="/brand-demo/AddServlet" method="post"> 品牌名称:<input name="brandName"><br> 企业名称:<input name="companyName"><br> 排序:<input name="ordered"><br> 描述信息:<textarea rows="5" cols="20" name="description"></textarea><br> 状态: <input type="radio" name="status" value="0">禁用 <input type="radio" name="status" value="1">启用<br> <input type="submit" value="提交"> </form> </body> </html>
AddBrandServlet
package com.ruochen.web; import com.ruochen.pojo.Brand; import com.ruochen.service.BrandService; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/addServlet") public class AddServlet extends HttpServlet { private BrandService service = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 接收表单提交的数据,封装为一个 Brand 对象 String brandName = request.getParameter("brandName"); String companyName = request.getParameter("companyName"); String ordered = request.getParameter("ordered"); String description = request.getParameter("description"); String status = request.getParameter("status"); Brand brand = new Brand(); brand.setBrandName(brandName); brand.setCompanyName(companyName); brand.setOrdered(Integer.parseInt(ordered)); brand.setDescription(description); brand.setStatus(Integer.parseInt(status)); // 2. 调用 service 完成添加 service.add(brand); // 3. 转发到查询所有 Servlet request.getRequestDispatcher("/selectAllServlet").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
- 测试
业务 - 修改(数据回显)
- Dao 层:
BrandMapper
/** * 根据 id 查询 * @param id * @return */ @Select("select * from tb_brand where id = #{id}") @ResultMap("brandResultMap") Brand selectById(int id);
- Service 层:
BrandService
/** * 根据 id 查询 * @param id * @return */ public Brand selectById(int id) { // 调用BrandMapper.selectAll() // 2. 获取 SqlSession SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 Brand brand = mapper.selectById(id); // 5. 释放资源 sqlSession.close(); return brand; }
- Web 层:
brand.jsp
<td><a href="/brand-demo/selectByIdServlet?id=${brand.id}">修改</a> <a href="#">删除</a></td>
SelectByIdServlet
package com.ruochen.web; import com.ruochen.pojo.Brand; import com.ruochen.service.BrandService; 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("/selectByIdServlet") public class SelectByIdServlet extends HttpServlet { private BrandService brandService = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 接收id String id = request.getParameter("id"); // 2. 调用 service Brand brand = brandService.selectById(Integer.parseInt(id)); // 3. 存储到 request 中 request.setAttribute("brand", brand); // 4. 转发到 update.jsp request.getRequestDispatcher("/update.jsp").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
update.jsp
<%-- Created by IntelliJ IDEA. User: ruochen Date: 2022/2/27 Time: 13:32 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <meta charset="UTF-8"> <title>修改品牌</title> </head> <body> <h3>修改品牌</h3> <form action="#" method="post"> 品牌名称:<input name="brandName" value="${brand.brandName}"><br> 企业名称:<input name="companyName" value="${brand.companyName}"><br> 排序:<input name="ordered" value="${brand.ordered}"><br> 描述信息:<textarea rows="5" cols="20" name="description">${brand.description}</textarea><br> 状态: <c:if test="${brand.status == 0}"> <input type="radio" name="status" value="0" checked>禁用 <input type="radio" name="status" value="1">启用<br> </c:if> <c:if test="${brand.status == 1}"> <input type="radio" name="status" value="0">禁用 <input type="radio" name="status" value="1" checked>启用<br> </c:if> <input type="submit" value="提交"> </form> </body> </html>
- 测试
业务 - 修改(修改数据)
- Dao 层:
BrandMapper
/** * 修改 * @param brand */ @Update("update tb_brand set brand_name = #{brandName}, company_name = #{companyName}, ordered = #{ordered}, " + "description = #{description}, status = #{status} where id = #{id}") void update(Brand brand);
- Service 层:
BrandService
/** * 修改 * @param brand */ public void update(Brand brand) { // 2. 获取 SqlSession SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 mapper.update(brand); // 提交事务 sqlSession.commit(); // 释放资源 sqlSession.close(); }
- Web 层:
update.jsp
<%-- Created by IntelliJ IDEA. User: ruochen Date: 2022/2/27 Time: 13:32 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <meta charset="UTF-8"> <title>修改品牌</title> </head> <body> <h3>修改品牌</h3> <form action="/brand-demo/updateServlet" method="post"> <%-- 隐藏域,提交 id --%> <input type="hidden" name="id" value="${brand.id}"> 品牌名称:<input name="brandName" value="${brand.brandName}"><br> 企业名称:<input name="companyName" value="${brand.companyName}"><br> 排序:<input name="ordered" value="${brand.ordered}"><br> 描述信息:<textarea rows="5" cols="20" name="description">${brand.description}</textarea><br> 状态: <c:if test="${brand.status == 0}"> <input type="radio" name="status" value="0" checked>禁用 <input type="radio" name="status" value="1">启用<br> </c:if> <c:if test="${brand.status == 1}"> <input type="radio" name="status" value="0">禁用 <input type="radio" name="status" value="1" checked>启用<br> </c:if> <input type="submit" value="提交"> </form> </body> </html>
updateServlet
package com.ruochen.web; import com.ruochen.pojo.Brand; import com.ruochen.service.BrandService; 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("/updateServlet") public class UpdateServlet extends HttpServlet { private BrandService service = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 处理 post 请求的乱码问题 request.setCharacterEncoding("utf-8"); // 1. 接收表单提交的数据,封装为一个 Brand 对象 String id = request.getParameter("id"); String brandName = request.getParameter("brandName"); String companyName = request.getParameter("companyName"); String ordered = request.getParameter("ordered"); String description = request.getParameter("description"); String status = request.getParameter("status"); Brand brand = new Brand(); brand.setId(Integer.parseInt(id)); brand.setBrandName(brandName); brand.setCompanyName(companyName); brand.setOrdered(Integer.parseInt(ordered)); brand.setDescription(description); brand.setStatus(Integer.parseInt(status)); // 2. 调用 service 完成修改 service.update(brand); // 3. 转发到查询所有 Servlet request.getRequestDispatcher("/selectAllServlet").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
- 测试
业务 - 删除
- Dao 层:
BrandMapper
/** * 删除 * @param id */ @Delete("delete from tb_brand where id = #{id}") void delete(int id);
- Service 层:
BrandService
/** * 删除 * @param id */ public void delete(int id) { // 2. 获取 SqlSession SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 mapper.delete(id); // 提交事务 sqlSession.commit(); // 释放资源 sqlSession.close(); }
- Web 层:
brand.jsp
<td><a href="/brand-demo/selectByIdServlet?id=${brand.id}">修改</a> <a href="/brand-demo/deleteServlet?id=${brand.id}">删除</a></td>
DeleteServlet
package com.ruochen.web; import com.ruochen.pojo.Brand; import com.ruochen.service.BrandService; 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("/deleteServlet") public class DeleteServlet extends HttpServlet { private BrandService service = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 接收 id String id = request.getParameter("id"); // 2. 调用 service service.delete(Integer.parseInt(id)); // 3. 转发到查询所有 Servlet request.getRequestDispatcher("/selectAllServlet").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
- 测试
业务 - 用户登录
- Dao 层:
UserMapper.java
package com.ruochen.mapper; import com.ruochen.pojo.User; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; public interface UserMapper { /** * 根据用户名和密码查询用户对象 * @param username * @param password * @return */ @Select("select * from tb_user where username = #{username} and password = #{password}") User select(@Param("username") String username,@Param("password") String password); /** * 根据用户名查询用户对象 * @param username * @return */ @Select("select * from tb_user where username = #{username}") User selectByUsername(String username); /** * 添加用户 * @param user */ @Insert("insert into tb_user values(null,#{username},#{password})") void add(User user); }
User.java
package com.ruochen.pojo; 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 + ''' + '}'; } }
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.ruochen.mapper.UserMapper"> </mapper>
- Service 层:
UserService.java
package com.ruochen.service; import com.ruochen.mapper.UserMapper; import com.ruochen.pojo.User; import com.ruochen.utils.SqlSessionFactoryUtils; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; public class UserService { SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory(); /** * 登录方法 * @param username * @param password * @return */ public User login(String username, String password) { // 2. 获取 SqlSession SqlSession sqlSession = factory.openSession(); // 3. 获取 UserMapper UserMapper mapper = sqlSession.getMapper(UserMapper.class); // 4. 调用方法 User user = mapper.select(username, password); // 5. 释放资源 sqlSession.close(); return user; } }
- Web 层:
login.jsp
<%-- Created by IntelliJ IDEA. User: ruochen Date: 2022/2/27 Time: 15:45 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta charset="UTF-8"> <title>login</title> <link href="css/login.css" rel="stylesheet"> </head> <body> <div id="loginDiv" style="height: 350px"> <form action="/brand-demo/loginServlet" id="form"> <h1 id="loginMsg">LOGIN IN</h1> <div id="errorMsg">${login_msg}</div> <p>Username:<input id="username" name="username" type="text"></p> <p>Password:<input id="password" name="password" type="password"></p> <p>Remember:<input id="remember" name="remember" type="checkbox"></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>
brand.jsp
添加
<h1>${user.username},欢迎您</h1>
LoginServlet
package com.ruochen.web; import com.ruochen.pojo.User; import com.ruochen.service.UserService; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/loginServlet") public class LoginServlet extends HttpServlet { private UserService service = new UserService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 获取用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); // 2. 调用 service 查询 User user = service.login(username, password); // 3. 判断 if (user != null) { // 登录成功,,跳转到查询所有的 BrandServlet // 将登录成功的user对象存储到 session HttpSession session = request.getSession(); session.setAttribute("user", user); String contextPath = request.getContextPath(); response.sendRedirect(contextPath + "/selectAllServlet"); } else { // 登录失败 // 存储错误信息到 request request.setAttribute("login_msg", "用户名或密码错误"); // 跳转到 login.jsp request.getRequestDispatcher("/login.jsp").forward(request, response); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
- 测试
业务 - 记住用户
- 如何自动填充用户名和密码?
- 将用户名和密码写入Cookie中,并且持久化存储 Cookie,下次访问浏览器会自动携带 Cookie
- 在页面获取 Cookie 数据后,设置到用户名和密码框中
- 何时写 Cookie?
- 登录成功
- 用户勾选记住用户复选框
LoginServlet
package com.ruochen.web; import com.ruochen.pojo.User; import com.ruochen.service.UserService; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/loginServlet") public class LoginServlet extends HttpServlet { private UserService service = new UserService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 获取用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); // 获取复选框数据 String remember = request.getParameter("remember"); // 2. 调用 service 查询 User user = service.login(username, password); // 3. 判断 if (user != null) { // 登录成功,,跳转到查询所有的 BrandServlet // 判断用户是否勾选记住我 if ("1".equals(remember)) { // 勾选了,发送 Cookie // 1. 创建 Cookie 对象 Cookie c_username = new Cookie("username", username); Cookie c_password = new Cookie("password", password); // 设置 Cookie 存活时间 c_username.setMaxAge(60 * 60 * 24 * 7); c_password.setMaxAge(60 * 60 * 24 * 7); // 2. 发送 Cookie response.addCookie(c_username); response.addCookie(c_password); } // 将登录成功的user对象存储到 session HttpSession session = request.getSession(); session.setAttribute("user", user); String contextPath = request.getContextPath(); response.sendRedirect(contextPath + "/selectAllServlet"); } else { // 登录失败 // 存储错误信息到 request request.setAttribute("login_msg", "用户名或密码错误"); // 跳转到 login.jsp request.getRequestDispatcher("/login.jsp").forward(request, response); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
login.jsp
<%-- Created by IntelliJ IDEA. User: ruochen Date: 2022/2/27 Time: 15:45 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta charset="UTF-8"> <title>login</title> <link href="css/login.css" rel="stylesheet"> </head> <body> <div id="loginDiv" style="height: 350px"> <form action="/brand-demo/loginServlet" method="post" id="form"> <h1 id="loginMsg">LOGIN IN</h1> <div id="errorMsg">${login_msg}</div> <p>Username:<input id="username" name="username" value="${cookie.username.value}" type="text"></p> <p>Password:<input id="password" name="password" value="${cookie.password.value}" type="password"></p> <p>Remember:<input id="remember" name="remember" value="1" type="checkbox"></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>
- 测试
业务 - 注册
UserService.java
/** * 注册方法 * * @param user * @return */ public boolean register(User user) { // 2. 获取 SqlSession SqlSession sqlSession = factory.openSession(); // 3. 获取 UserMapper UserMapper mapper = sqlSession.getMapper(UserMapper.class); // 4. 判断用户名是否存在 User u = mapper.selectByUsername(user.getUsername()); if (u == null) { // 用户名不存在,注册 mapper.add(user); sqlSession.commit(); } sqlSession.close(); return u == null; }
register.jsp
<%-- Created by IntelliJ IDEA. User: ruochen Date: 2022/2/27 Time: 16:24 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <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="/brand-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">${register_msg}</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> <tr> <td>验证码</td> <td class="inputs"> <input name="checkCode" type="text" id="checkCode"> <img src="imgs/a.jpg"> <a href="#" id="changeImg">看不清?</a> </td> </tr> </table> <div class="buttons"> <input value="注 册" type="submit" id="reg_btn"> </div> <br class="clear"> </form> </div> </body> </html>
login.jsp
添加<div id="errorMsg">${login_msg} ${register_msg}</div> <a href="register.jsp">没有账号?</a>
RegisterServlet
package com.ruochen.web; import com.ruochen.pojo.User; import com.ruochen.service.UserService; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException; @WebServlet("/registerServlet") public class RegisterServlet extends HttpServlet { private UserService service = new UserService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 获取用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); User user = new User(); user.setUsername(username); user.setPassword(password); // 2. 调用 service 注册 boolean flag = service.register(user); // 3. 判断注册成功与否 if (flag) { // 注册成功,跳转登录页面 request.setAttribute("register_msg", "注册成功,请登录"); request.getRequestDispatcher("/login.jsp").forward(request, response); } else { // 注册失败,跳转到注册页面 request.setAttribute("register_msg", "用户名已存在"); request.getRequestDispatcher("/register.jsp").forward(request, response); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
- 测试
业务 - 注册验证码
- 验证码工具类:
checkCodeUtil.java
package com.ruochen.utils; import javax.imageio.ImageIO; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.*; import java.util.Arrays; import java.util.Random; /** * 生成验证码工具类 */ public class CheckCodeUtil { public static final String VERIFY_CODES = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static Random random = new Random(); /** * 输出随机验证码图片流,并返回验证码值(一般传入输出流,响应response页面端,Web项目用的较多) * * @param w 图片宽度 * @param h 图片高度 * @param os 输出流 * @param verifySize 数据长度 * @return 验证码数据 * @throws IOException */ public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException { String verifyCode = generateVerifyCode(verifySize); outputImage(w, h, os, verifyCode); return verifyCode; } /** * 使用系统默认字符源生成验证码 * * @param verifySize 验证码长度 * @return */ public static String generateVerifyCode(int verifySize) { return generateVerifyCode(verifySize, VERIFY_CODES); } /** * 使用指定源生成验证码 * * @param verifySize 验证码长度 * @param sources 验证码字符源 * @return */ public static String generateVerifyCode(int verifySize, String sources) { // 未设定展示源的字码,赋默认值大写字母+数字 if (sources == null || sources.length() == 0) { sources = VERIFY_CODES; } int codesLen = sources.length(); Random rand = new Random(System.currentTimeMillis()); StringBuilder verifyCode = new StringBuilder(verifySize); for (int i = 0; i < verifySize; i++) { verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1))); } return verifyCode.toString(); } /** * 生成随机验证码文件,并返回验证码值 (生成图片形式,用的较少) * * @param w * @param h * @param outputFile * @param verifySize * @return * @throws IOException */ public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException { String verifyCode = generateVerifyCode(verifySize); outputImage(w, h, outputFile, verifyCode); return verifyCode; } /** * 生成指定验证码图像文件 * * @param w * @param h * @param outputFile * @param code * @throws IOException */ public static void outputImage(int w, int h, File outputFile, String code) throws IOException { if (outputFile == null) { return; } File dir = outputFile.getParentFile(); //文件不存在 if (!dir.exists()) { //创建 dir.mkdirs(); } try { outputFile.createNewFile(); FileOutputStream fos = new FileOutputStream(outputFile); outputImage(w, h, fos, code); fos.close(); } catch (IOException e) { throw e; } } /** * 输出指定验证码图片流 * * @param w * @param h * @param os * @param code * @throws IOException */ public static void outputImage(int w, int h, OutputStream os, String code) throws IOException { int verifySize = code.length(); BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Random rand = new Random(); Graphics2D g2 = image.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 创建颜色集合,使用java.awt包下的类 Color[] colors = new Color[5]; Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.YELLOW}; float[] fractions = new float[colors.length]; for (int i = 0; i < colors.length; i++) { colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)]; fractions[i] = rand.nextFloat(); } Arrays.sort(fractions); // 设置边框色 g2.setColor(Color.GRAY); g2.fillRect(0, 0, w, h); Color c = getRandColor(200, 250); // 设置背景色 g2.setColor(c); g2.fillRect(0, 2, w, h - 4); // 绘制干扰线 Random random = new Random(); // 设置线条的颜色 g2.setColor(getRandColor(160, 200)); for (int i = 0; i < 20; i++) { int x = random.nextInt(w - 1); int y = random.nextInt(h - 1); int xl = random.nextInt(6) + 1; int yl = random.nextInt(12) + 1; g2.drawLine(x, y, x + xl + 40, y + yl + 20); } // 添加噪点 // 噪声率 float yawpRate = 0.05f; int area = (int) (yawpRate * w * h); for (int i = 0; i < area; i++) { int x = random.nextInt(w); int y = random.nextInt(h); // 获取随机颜色 int rgb = getRandomIntColor(); image.setRGB(x, y, rgb); } // 添加图片扭曲 shear(g2, w, h, c); g2.setColor(getRandColor(100, 160)); int fontSize = h - 4; Font font = new Font("Algerian", Font.ITALIC, fontSize); g2.setFont(font); char[] chars = code.toCharArray(); for (int i = 0; i < verifySize; i++) { AffineTransform affine = new AffineTransform(); affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize / 2, h / 2); g2.setTransform(affine); g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10); } g2.dispose(); ImageIO.write(image, "jpg", os); } /** * 随机颜色 * * @param fc * @param bc * @return */ private static Color getRandColor(int fc, int bc) { if (fc > 255) { fc = 255; } if (bc > 255) { bc = 255; } int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } private static int getRandomIntColor() { int[] rgb = getRandomRgb(); int color = 0; for (int c : rgb) { color = color << 8; color = color | c; } return color; } private static int[] getRandomRgb() { int[] rgb = new int[3]; for (int i = 0; i < 3; i++) { rgb[i] = random.nextInt(255); } return rgb; } private static void shear(Graphics g, int w1, int h1, Color color) { shearX(g, w1, h1, color); shearY(g, w1, h1, color); } private static void shearX(Graphics g, int w1, int h1, Color color) { int period = random.nextInt(2); boolean borderGap = true; int frames = 1; int phase = random.nextInt(2); for (int i = 0; i < h1; i++) { double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); g.copyArea(0, i, w1, 1, (int) d, 0); if (borderGap) { g.setColor(color); g.drawLine((int) d, i, 0, i); g.drawLine((int) d + w1, i, w1, i); } } } private static void shearY(Graphics g, int w1, int h1, Color color) { int period = random.nextInt(40) + 10; // 50; boolean borderGap = true; int frames = 20; int phase = 7; for (int i = 0; i < w1; i++) { double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); g.copyArea(i, 0, 1, h1, 0, (int) d); if (borderGap) { g.setColor(color); g.drawLine(i, (int) d, i, 0); g.drawLine(i, (int) d + h1, i, h1); } } } }
register.jsp
<tr> <td>验证码</td> <td class="inputs"> <input name="checkCode" type="text" id="checkCode"> <img id="checkCodeImg" src="/brand-demo/checkCodeServlet"> <a href="#" id="changeImg">看不清?</a> </td> </tr> <script> document.getElementById("changeImg").onclick = function () { document.getElementById("checkCodeImg").src = "/brand-demo/checkCodeServlet?" + new Date().getMilliseconds(); }; document.getElementById("checkCodeImg").onclick = function () { document.getElementById("checkCodeImg").src = "/brand-demo/checkCodeServlet?" + new Date().getMilliseconds(); }; </script>
CheckCodeServlet.java
package com.ruochen.web; import com.ruochen.utils.CheckCodeUtil; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; @WebServlet("/checkCodeServlet") public class CheckCodeServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 生成验证码 ServletOutputStream os = response.getOutputStream(); String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, os, 4); // 存入 session HttpSession session = request.getSession(); session.setAttribute("checkCodeGen", checkCode); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
RegisterServlet.java
package com.ruochen.web; import com.ruochen.pojo.User; import com.ruochen.service.UserService; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException; @WebServlet("/registerServlet") public class RegisterServlet extends HttpServlet { private UserService service = new UserService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 获取用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); User user = new User(); user.setUsername(username); user.setPassword(password); // 获取用户输入的验证码 String checkCode = request.getParameter("checkCode"); // 程序生成的验证码,从 session 获取 HttpSession session = request.getSession(); String checkCodeGen = (String) session.getAttribute("checkCodeGen"); // 比对 if (!checkCodeGen.equalsIgnoreCase(checkCode)) { request.setAttribute("register_msg", "验证码错误"); request.getRequestDispatcher("/register.jsp").forward(request, response); // 不允许注册 return; } // 2. 调用 service 注册 boolean flag = service.register(user); // 3. 判断注册成功与否 if (flag) { // 注册成功,跳转登录页面 request.setAttribute("register_msg", "注册成功,请登录"); request.getRequestDispatcher("/login.jsp").forward(request, response); } else { // 注册失败,跳转到注册页面 request.setAttribute("register_msg", "用户名已存在"); request.getRequestDispatcher("/register.jsp").forward(request, response); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
- 测试
业务 - 登录验证
LoginFilter
package com.ruochen.web.filter; import javax.servlet.*; import javax.servlet.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.io.IOException; /** * 登录验证的过滤器 */ @WebFilter("/*") public class LoginFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { HttpServletRequest req = (HttpServletRequest) request; // 判断访问资源路径是否和登录注册相关 String[] urls = {"/login.jsp", "/imgs/", "/css/", "/loginServlet", "/register.jsp", "/registerServlet", "/checkCodeServlet"}; // 获取当前访问的资源路径 String url = req.getRequestURL().toString(); // 循环判断 for (String u : urls) { if (url.contains(u)) { // 包含 // 放行 chain.doFilter(request, response); return; } } // 1. 判断 session 中是否有 user HttpSession session = req.getSession(); Object user = session.getAttribute("user"); // 2. 判断user是否为 null if (user != null) { // 已登录 // 放行 chain.doFilter(request, response); } else { // 未登录,存储提示信息,跳转到登录页面 req.setAttribute("login_msg", "您尚未登录!"); req.getRequestDispatcher("/login.jsp").forward(req, response); } } public void init(FilterConfig config) throws ServletException { } public void destroy() { } }
- 测试
最后
以上就是成就战斗机为你收集整理的Servlet 详细教程 + 案例的全部内容,希望文章能够帮你解决Servlet 详细教程 + 案例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复