当前位置: 首页 > news >正文

小黑子—JavaWeb:第五章 - JSP与会话跟踪技术

JavaWeb入门5.0

  • 1. JSP
    • 1.1 JSP快速入门
    • 1.2 JSP原理
    • 1.3 JSP脚本
      • 1.3.1 JSP缺点
    • 1.4 EL 表达式
    • 1.5 JSTL 标签
      • 1.5.1 JSTL 快速入门
        • 1.5.1 - I JSTL标签if
        • 1.5.1 - II JSTL标签forEach
    • 1.6 MVC模式
    • 1.7 三层架构
    • 1.8 实现案例
      • 1.8.1 环境准备
      • 1.8.2 查询所有
      • 1.8.3 添加数据
      • 1.8.4 修改
        • 1.8.4 - I 修改回显数据
        • 1.8.4 - II 修改数据
  • 2. 会话跟踪技术
    • 2.1 Cookie
      • 2.1.1 Cookie基本使用
      • 2.1.2 Cookie原理
      • 2.1.3 Cookie使用细节
    • 2.2 Session
      • 2.2.1 Session基本使用
      • 2.2.2 Session原理
      • 2.2.3 Session使用细节
    • 2.3 小结
    • 2.4 案例
      • 2.4.1 用户登录
      • 2.4.2 记住用户
        • 2.4.2 - I 写cookie
        • 2.4.2 - II 获取cookie
      • 2.4.3 用户注册
      • 2.4.4 验证码
        • 2.4.4 - I 校验验证码

1. JSP

概念:Java Server Pags,java服务端页面

  • 一种动态的网页接收,其中即可以定义HTML、JS、CSS等静态内容,还可以定义Java代码的动态内容
  • JSP = HTML + Java
    在这里插入图片描述

1.1 JSP快速入门

  1. 导入JSP坐标
    <dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version><scope>provided</scope></dependency>
  1. 创建JSP文件
    在这里插入图片描述

  2. 编写HTML标签和Java代码
    在这里插入图片描述

案例:

<html>
<head><title>Title</title>
</head>
<body><h1>JSP,hello</h1><%System.out.println("hello jsp");%>
</body>
</html>

在这里插入图片描述

在这里插入图片描述

1.2 JSP原理

  • JSP本质上就是一个Servlet
  • JSP在被访问时,由JSP容器(Tomcat)将其转换为Java文件(Servlet),在由JSP容器(Tomcat)将其编译,最终对外提供服务的其实就是这个字节码文件
    在这里插入图片描述

1.3 JSP脚本

  • JSP脚本用于在JSP页面内定义Java代码.
  • JSP脚本分类:
    1、 <%...%>:内容会直接放到_jspService()方法之中
    2、<%=...%>:内容会放到out.print()中,作为out.print()的参数
    3、<%!..%>:内容会放到_jspService()方法之外,被类直接包含

例子:
注意使用maven插件的tomcat7运行时最好对应的jdk版本为1.8,如果jdk版本太高可能会出现jsp编译不了的情况(500报错之一)
解决方案:

    • 1.在设置里面,Build->创建工具->Maven->运行程序下找到JRE条件jdk版本
    • 2.自行在创建项目时使用低版本的jdk
    • 3.具体分析java语法变换,下例情况去掉System
<%--Created by IntelliJ IDEA.User: 19148Date: 2023/7/31Time: 9:46To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><h1>JSP,hello</h1><%out.println("hello,jsp");int i = 3;%><%="hello"%><%=i%><%!void show(){}String name = "zhangsan";%>
</body>
</html>

在这里插入图片描述
在这里插入图片描述

练习:
在这里插入图片描述
Brand类:

package com.itheima.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;}@Overridepublic String toString() {return "Brand{" +"id=" + id +", brandName='" + brandName + '\'' +", companyName='" + companyName + '\'' +", ordered=" + ordered +", description='" + description + '\'' +", status=" + status +'}';}
}

brand.jsp:

<%@ page import="com.itheima.pojo.Brand" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %><%--Created by IntelliJ IDEA.User: 19148Date: 2023/8/1Time: 12:19To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%//查询数据库List<Brand> brands = new ArrayList<Brand>();brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));
%><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<input type="button" value="新增"><br>
<hr>
<table border="1" cellspacing="0" width="800"><tr><th>序号</th><th>品牌名称</th><th>企业名称</th><th>排序</th><th>品牌介绍</th><th>状态</th><th>操作</th></tr><%for (int i = 0; i < brands.size(); i++) {Brand brand = brands.get(i);%><tr align="center"><td><%=brand.getId()%></td><td><%=brand.getBrandName()%></td><td><%=brand.getCompanyName()%></td><td><%=brand.getOrdered()%></td><td><%=brand.getDescription()%></td><%if(brand.getStatus()==1){//显示启用%><td><%="启用"%></td><%}else {//显示禁用%><td><%="禁用"%></td><%}%><td><a href="#">修改</a> <a href="#">删除</a></td></tr><%}%></table></body>
</html>

在这里插入图片描述

1.3.1 JSP缺点

在这里插入图片描述

由于JSP页面内,既可以定义HTML标签,又可以定义Java代码,造成了以下问题:

  1. 书写麻烦:特别是复杂的页面
  2. 阅读麻烦
  3. 复杂度高:运行需要依赖于各种环境,JRE,JSP容器,JavaEE…
  4. 占内存和磁盘:JSP会自动生成.java和.class文件占磁盘,运行的是.class文件占内存
  5. 调试困难:出错后,需要找到自动生成的.java文件进行调试
  6. 不利于团队协作:前端人员不会Java,后端人员不精HTML

演变过程:
在这里插入图片描述

1.4 EL 表达式

Expression Language表达式语言,用于简化JSP页面内的Java代码

  • 主要功能:获取数据

语法:${expression}
${brands}:获取域中存储的key为brands的数据

JavaWeb中的四大域对象:

  1. page:当前页面有效
  2. request:当前请求有效
  3. session:当前会话有效
  4. application:当前应用有效

例子:
ServletDemo1:

@WebServlet("/demo1")
public class ServletDemo1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.准备数据List<Brand> brands = new ArrayList<Brand>();brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));//2.储存到request域中request.setAttribute("brands",brands);//3.转发到el-demo.jsprequest.getRequestDispatcher("/el-demo.jsp").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

el-demo.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head><title>Title</title>
</head>
<body>${brands}</body>
</html>

如果只是显示 ${brands}的话,在头部加上isELIgnored="false"即可
在这里插入图片描述

el表达式获取数据,会依次从这4个域中寻找,直到找到为止
在这里插入图片描述

1.5 JSTL 标签

JSP标准标签库(Jsp Standarded Tag Library),使用标签取代JSP页面上的Java代码

例如:

<c:if test="${flag ==1}"></c:if>
<c:if test="${flag == 2}"></c:if>

在这里插入图片描述

1.5.1 JSTL 快速入门

  1. 导入坐标
<dependency><groupId>jstl</groupId><artifactId>jstl<lartifactId><version>1.2</version>
</dependency>
<dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version>
</dependency>
  1. 在JSP页面上引入JSTL标签库
<%@ taglib prefix= "c" uri= "http://java.sun.com/jsp/jstl/core" %>
  1. 使用
    • <C:if>

1.5.1 - I JSTL标签if

例子:
ServletDemo1类修改部分:
在这里插入图片描述
jstl-if.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java"  isELIgnored="false" %>
<html>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><head><title>Title</title>
</head>
<body>
<%--c:if 来完成逻辑判断,替换java if else
--%><%--    <c:if test="true">--%>
<%--        <h1>true</h1>--%>
<%--    </c:if>--%>
<%--    <c:if test="false">--%>
<%--        <h1>false</h1>--%>
<%--    </c:if>--%><c:if test="${status ==1}">启用</c:if><c:if test="${status ==0}">禁用</c:if>
</body>
</html>

显示如果空白的话,添加:isELIgnored=“false”
在这里插入图片描述

1.5.1 - II JSTL标签forEach

<c:forEach>:相当于for循环

  • items:被遍历的容器
  • var:遍历产生的临时变量
  • varStatus:遍历状态对象
  • count:从1开始遍历的数字
  • status:从0开始遍历的数字
    在这里插入图片描述

例子:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<input type="button" value="新增"><br>
<hr>
<table border="1" cellspacing="0" width="800"><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>${brand.id}</td>--%><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>

在这里插入图片描述

  • begin:开始数
  • end:结束数
  • step:步长
    在这里插入图片描述

例子:

<c:forEach begin="1" end="10" step="1" var="i">
<%--  ${i}<br>--%><a href="#">${i}</a>
</c:forEach>

在这里插入图片描述

1.6 MVC模式

MVC是一种分层开发的模式,其中:

  • M: Model,业务模型,处理业务
  • V: View,视图,界面展示
  • C: Controller,控制器,处理请求,调用模型和视图
    在这里插入图片描述

MVC好处:

  1. 职责单一,互不影响
  2. 有利于分工协作
  3. 有利于组件重用

1.7 三层架构

  • 数据访问层:对数据库的CRUD基本操作
  • 业务逻辑层:对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能
  • 表现层:接收请求,封装数据,调用业务逻辑层,响应数据
    在这里插入图片描述

MVC和三层架构的区别:

在这里插入图片描述

1.8 实现案例

在这里插入图片描述

1.8.1 环境准备

在这里插入图片描述

  • 核心配置文件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>org.example</groupId><artifactId>brand-demo</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</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>8.0.30</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标准标签库--><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.2</version></plugin></plugins></build>
</project>
  • 创建目录结构包:
    在这里插入图片描述

  • 数据库的创建:

-- 删除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;
  • pojo下的Brand实体类
package com.itheima.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;}@Overridepublic String toString() {return "Brand{" +"id=" + id +", brandName='" + brandName + '\'' +", companyName='" + companyName + '\'' +", ordered=" + ordered +", description='" + description + '\'' +", status=" + status +'}';}
}
  • mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--起别名--><typeAliases><package name="com.itheima.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&amp;useServerPrepStmts=true"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><mappers><!--扫描mapper--><package name="com.itheima.mapper"/></mappers>
</configuration>
  • BrandMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.BrandMapper"></mapper>
  • BrandMapper.java
package com.itheima.mapper;public interface BrandMapper {
}

目录展示:
在这里插入图片描述

1.8.2 查询所有

在这里插入图片描述

  • brand.jsp
<%--Created by IntelliJ IDEA.User: 19148Date: 2023/8/2Time: 9:59To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><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>${brand.id}</td>--%><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>
  • BrandMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.BrandMapper"><resultMap id="brandResultMap" type="brand"><result column="brand_name" property="brandName"></result><result column="company_name" property="companyName"></result></resultMap>
</mapper>
  • BrandMapper.java
package com.itheima.mapper;import com.itheima.pojo.Brand;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Select;import java.util.List;public interface BrandMapper {//查询所有@Select("select * from tb_brand")@ResultMap("brandResultMap")List<Brand> selectAll();
}
  • BrandService.java
public class BrandService {SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();//查询所有功能public List<Brand> selectAll(){//调用BrandMapper.selectAll()//2.获取SqlSessionSqlSession sqlSession = factory.openSession();//3.获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4.调用方法List<Brand> brands = mapper.selectAll();sqlSession.close();return brands;}
}
  • 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>
  • SqlSessionFactoryUtils 类:
ublic 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;}
}
  • selectAllServlet:
@WebServlet("/selectAllServlet")
public class selectAllServlet extends HttpServlet {private BrandService service = new BrandService();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.调用BrandService完成查询List<Brand> brands = service.selectAll();//2.存入request域中request.setAttribute("brands",brands);//3.转发到brand.jsprequest.getRequestDispatcher("/brand.jsp").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

在这里插入图片描述

1.8.3 添加数据

在这里插入图片描述

  • brand.jsp:
<%--Created by IntelliJ IDEA.User: 19148Date: 2023/8/2Time: 9:59To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><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>${brand.id}</td>--%><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><script>document.getElementById("add").onclick = function (){location.href="/brand-demo/addBrand.jsp ";}
</script></body>
</html>
  • BrandMapper.java
public interface BrandMapper {//查询所有@Select("select * from tb_brand")@ResultMap("brandResultMap")List<Brand> selectAll();@Insert("insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status})")void add(Brand brand);
}
  • BrandService.java
public class BrandService {SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();//查询所有功能public List<Brand> selectAll(){//调用BrandMapper.selectAll()//2.获取SqlSessionSqlSession sqlSession = factory.openSession();//3.获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4.调用方法List<Brand> brands = mapper.selectAll();sqlSession.close();return brands;}public void add(Brand brand){//2.获取SqlSessionSqlSession sqlSession = factory.openSession();//3.获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4.调用方法mapper.add(brand);//提交事务sqlSession.commit();sqlSession.close();}}
  • addBrand.jsp
<%--Created by IntelliJ IDEA.User: 19148Date: 2023/8/2Time: 21:22To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!DOCTYPE html>
<html lang="en"><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>
  • AddServlet.java
@WebServlet("/AddServlet")
public class AddServlet extends HttpServlet {private BrandService service = new BrandService();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//处理post请求乱码问题request.setCharacterEncoding("utf-8");//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 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.转发到查询所有Servletrequest.getRequestDispatcher("/selectAllServlet").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

在这里插入图片描述

1.8.4 修改

在这里插入图片描述

1.8.4 - I 修改回显数据

在这里插入图片描述

  • BrandMapper.java
public interface BrandMapper {//查询所有@Select("select * from tb_brand")@ResultMap("brandResultMap")List<Brand> selectAll();@Insert("insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status})")void add(Brand brand);//根据id查询@Select("select * from tb_brand where id = #{id}")@ResultMap("brandResultMap")Brand selectById(int id);}
  • update.jsp
<%--Created by IntelliJ IDEA.User: 19148Date: 2023/8/2Time: 21:22To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>修改品牌</title>
</head>
<body>
<h3>修改品牌</h3>
<form action="/brand-demo/AddServlet" 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"> value="${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>
  • selectByIdServlet
WebServlet("/selectByIdServlet")
public class selectByIdServlet extends HttpServlet {private BrandService service = new BrandService();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.接收idString id = request.getParameter("id");//2.调用serivce查询Brand brand = service.selectById(Integer.parseInt(id));//3.存储到request中request.setAttribute("brand",brand);//4.转发到update.jsprequest.getRequestDispatcher("/update.jsp").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
  • BrandService
public class BrandService {SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();//查询所有功能public List<Brand> selectAll(){//调用BrandMapper.selectAll()//2.获取SqlSessionSqlSession sqlSession = factory.openSession();//3.获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4.调用方法List<Brand> brands = mapper.selectAll();sqlSession.close();return brands;}public void add(Brand brand){//2.获取SqlSessionSqlSession sqlSession = factory.openSession();//3.获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4.调用方法mapper.add(brand);//提交事务sqlSession.commit();sqlSession.close();}//根据id查询public Brand selectById(int id){//调用BrandMapper.selectAll()//2.获取SqlSessionSqlSession sqlSession = factory.openSession();//3.获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4.调用方法Brand brand = mapper.selectById(id);sqlSession.close();return brand;}
}

在这里插入图片描述

1.8.4 - II 修改数据

在这里插入图片描述

  • BrandMapper.java
public interface BrandMapper {//查询所有@Select("select * from tb_brand")@ResultMap("brandResultMap")List<Brand> selectAll();@Insert("insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status})")void add(Brand brand);//根据id查询@Select("select * from tb_brand where id = #{id}")@ResultMap("brandResultMap")Brand selectById(int id);//修改@Update("update tb_brand set brand_name = #{brandName},company_name=#{companyName},ordered=#{ordered},description=#{description},status=#{status} where id=#{id}")void update(Brand brand);
}
  • updateService.java
@WebServlet("/updateServlet")
public class updateServlet extends HttpServlet {private BrandService service = new BrandService();@Overrideprotected 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 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.转发到查询所有Servletrequest.getRequestDispatcher("/selectAllServlet").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
  • BrandService.java
public class BrandService {SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();//查询所有功能public List<Brand> selectAll(){//调用BrandMapper.selectAll()//2.获取SqlSessionSqlSession sqlSession = factory.openSession();//3.获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4.调用方法List<Brand> brands = mapper.selectAll();sqlSession.close();return brands;}//添加public void add(Brand brand){//2.获取SqlSessionSqlSession sqlSession = factory.openSession();//3.获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4.调用方法mapper.add(brand);//提交事务sqlSession.commit();sqlSession.close();}//根据id查询public Brand selectById(int id){//调用BrandMapper.selectAll()//2.获取SqlSessionSqlSession sqlSession = factory.openSession();//3.获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4.调用方法Brand brand = mapper.selectById(id);sqlSession.close();return brand;}//添加public void update(Brand brand){//2.获取SqlSessionSqlSession sqlSession = factory.openSession();//3.获取BrandMapperBrandMapper mapper = sqlSession.getMapper(BrandMapper.class);//4.调用方法mapper.update(brand);//提交事务sqlSession.commit();sqlSession.close();}}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2. 会话跟踪技术

  • 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应
  • 会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便于在同一次会话的多次请求间共享数据
  • HTTP协议是无状态的,每次浏览器向服务器请求时,服务器都会将该请求视为新的请求,因此我们需要会话跟踪技术来实现会话数据共享
    在这里插入图片描述

实现方式:

  1. 客户端会话跟踪技术:Cookie
  2. 服务端会话跟踪技术:Session

2.1 Cookie

2.1.1 Cookie基本使用

Cookie:客户端会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问

基本使用:
发送Cookie:

  1. 创建Cookie对象,设置数据
Cookie cookie = new Cookie("key","value");
  1. 发送Cookie到客户端:使用response对象
response.addCookie(cookie);

例如:

@WebServlet("/aServlet")
public class aServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//发送cookie//1.创建cookie对象Cookie cookie = new Cookie("username", "zs");//2.发送Cookie.responseresponse.addCookie(cookie);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

获取Cookie:

  1. 获取客户端携带的所有Cookie,使用request对象
Cookie[] cookies = request.getCookies();
  1. 遍历数组,获取每一个Cookie对象:for
cookie.getName();
  1. 使用Cookie对象方法获取数据
cookie.getName();
cookie.getValue();

例子:

@WebServlet("/bServlet")
public class bServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取cookie//1.获取Cookie数组Cookie[] cookies = request.getCookies();//2.遍历数组for (Cookie cookie : cookies) {//3.获取数据String name = cookie.getName();if("username".equals(name)){String value = cookie.getValue();System.out.println(name+":"+value);break;}}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

在这里插入图片描述
接收aServlet的cookie
在这里插入图片描述

2.1.2 Cookie原理

cookie的实现是基于HTTP协议的:

  • 响应头:set-cookie
  • 请求头:cookie
    在这里插入图片描述

2.1.3 Cookie使用细节

Cookie存活时间:

  • 默认情况下,Cookie存储在浏览器内存中,当浏览器关闭,内存释放,则Cookie被销毁
  • setMaxAge(int seconds):设置Cookie存活时间
    • 1、正数:将Cookie写入浏览器所在电脑的硬盘,持久化存储。到时间自动删除
    • 2、负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则Cookie被销毁
    • 3、零:删除对应Cookie

例子:

@WebServlet("/aServlet")
public class aServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//发送cookie//1.创建cookie对象Cookie cookie = new Cookie("username", "vanwot");//设置存活时间 7天cookie.setMaxAge((60*60*24*7));//2.发送Cookie.responseresponse.addCookie(cookie);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

在这里插入图片描述

在这里插入图片描述

Cookie存储中文:

  • Cookie不能直接存储中文
  • 如果需要存储,则需要进行转码:URL编码
//编码value = URLDecoder.encode(value,"UTF-8");
//解码value = URLDecoder.decode(value,"UTF-8");

例子:
aServelt:

@WebServlet("/aServlet")
public class aServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//发送cookie//1.创建cookie对象String value= "麻瓜";//URL编码value = URLEncoder.encode(value,"utf-8");System.out.println("储存数据:"+value);Cookie cookie = new Cookie("username", value);//设置存活时间 7天cookie.setMaxAge((60*60*24*7));//2.发送Cookie.responseresponse.addCookie(cookie);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

bServlet:

@WebServlet("/bServlet")
public class bServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取cookie//1.获取Cookie数组Cookie[] cookies = request.getCookies();//2.遍历数组for (Cookie cookie : cookies) {//3.获取数据String name = cookie.getName();if("username".equals(name)){String value = cookie.getValue();System.out.println(name+":"+value);//URL解码value = URLDecoder.decode(value,"utf-8");System.out.println(name+":"+value);break;}}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

在这里插入图片描述

2.2 Session

2.2.1 Session基本使用

服务端会话跟踪技术:将数据保存到服务端
JavaEE提供HttpSession接口,来实现一次会话的多次请求间数据共享功能

使用:

  1. 获取Session对象
HttpSession session = request.getSession();
  1. Session对象功能:
    • void setAttribute(String name, Object o):存储数据到session域中
    • Object getAttribute(String name):根据key,获取值
    • void removeAttribute(String name):根据key,删除该键值对
      在这里插入图片描述

例子:
SessionDemo1:

@WebServlet("/demo1")
public class SessionDemo1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//存储到Session中//1.获取Session对象HttpSession session = request.getSession();//2.存储数据session.setAttribute("username","vanwot");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

SessionDemo2:

@WebServlet("/demo2")
public class SessionDemo2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取数据,从session中//1.获取Session对象HttpSession session = request.getSession();//2.获取数据Object username = session.getAttribute("username");System.out.println(username);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

在这里插入图片描述

2.2.2 Session原理

Session是基于Cookie实现的
在这里插入图片描述

2.2.3 Session使用细节

Session钝化、活化:

  • 服务器重启后,Session中的数据是否还在?
  • 钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘的文件中
  • 活化:再次启动服务器后,从文件中加载数据到Session中

Seesion销毁:

  • 默认情况下,无操作,30分钟自动销毁
    • 配置在web-xml文件中
<session-config><session-timeout>30</session-timeout>
</session-config>
  • 调用Session对象的invalidate()方法

2.3 小结

Cookie和Session都是完成一次会话内多次请求间数据共享的

其区别:

  • 存储位置:Cookie是将数据存储在客户端,Session将数据存储在服务端
  • 安全性:Cookie不安全,Session安全
  • 数据大小:Cookie最大3KB,Session无大小限制
  • 存储时间:Cookie可以长期存储,Session默认30分钟
  • 服务器性能:Cookie不占服务器资源,Session占用服务器资源

2.4 案例

在这里插入图片描述

2.4.1 用户登录

在这里插入图片描述
在brand-demo的webapp下导入原来的:
在这里插入图片描述
UserMapper:

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实体类:

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;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.UserMapper"></mapper>

UserService:

public class UserService {SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();//登录方法public User login(String username,String password){//2.获取SqlSessionSqlSession sqlSession = factory.openSession();//3.获取UserMapperUserMapper mapper = sqlSession.getMapper(UserMapper.class);//4.调用方法User user = mapper.select(username, password);sqlSession.close();return user;}
}

loginServlet:

@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {private UserService service = new UserService();@Overrideprotected 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 {//登录失败//存储错误信息到requestrequest.setAttribute("login_msg","用户名或密码错误");//跳转到login.jsprequest.getRequestDispatcher("/login.jsp").forward(request,response);}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

用户名和密码错误时:
在这里插入图片描述
正确时:
在这里插入图片描述

2.4.2 记住用户

2.4.2 - I 写cookie

在这里插入图片描述

  • login.jsp
<%--Created by IntelliJ IDEA.User: 19148Date: 2023/8/4Time: 23:39To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!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" 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" value="1" type="checkbox"></p><div id="subDiv"><input type="submit" class="button" value="login up"><input type="reset" class="button" value="reset">&nbsp;&nbsp;&nbsp;<a href="register.html">没有账号?</a></div></form>
</div></body>
</html>
  • loginService
@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {private UserService service = new UserService();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.获取用户名和密码String username = request.getParameter("username");String password = request.getParameter("password");//获取复选框数据String remenber = request.getParameter("remenber");//2.调用service查询User user = service.login(username,password);//3.判断if(user !=null){//登录成功,跳转到查询所有的BrandServlet//判断用户是否勾选记住我if ("1".equals(remenber)){//勾选了,发送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.发送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 {//登录失败//存储错误信息到requestrequest.setAttribute("login_msg","用户名或密码错误");//跳转到login.jsprequest.getRequestDispatcher("/login.jsp").forward(request,response);}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

勾选登录成功后:
在这里插入图片描述

2.4.2 - II 获取cookie

在这里插入图片描述

刷新后:

  • login.jsp
<%--Created by IntelliJ IDEA.User: 19148Date: 2023/8/4Time: 23:39To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!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" 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" 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">&nbsp;&nbsp;&nbsp;<a href="register.html">没有账号?</a></div></form>
</div></body>
</html>

在这里插入图片描述

2.4.3 用户注册

在这里插入图片描述
在这里插入图片描述

  • register.jsp
<%--Created by IntelliJ IDEA.User: 19148Date: 2023/8/5Time: 10:47To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!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="/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>
  • registerService
package com.itheima.web;import com.itheima.pojo.User;
import com.itheima.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();@Overrideprotected 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);}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
  • login.jsp
<%--Created by IntelliJ IDEA.User: 19148Date: 2023/8/4Time: 23:39To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!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" style="height: 350px"><form action="/brand-demo/loginServlet" id="form"><h1 id="loginMsg">LOGIN IN</h1><div id="errorMsg">${login_msg}${register_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">&nbsp;&nbsp;&nbsp;<a href="register.jsp">没有账号?</a></div></form>
</div></body>
</html>

成功:
在这里插入图片描述
在这里插入图片描述
失败:
在这里插入图片描述

2.4.4 验证码

在这里插入图片描述

CheckCodeUtil类:

package com.itheima.util;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();public static void main(String[] args) throws IOException {OutputStream fos = new FileOutputStream("E://JSP-demo1/brand-demo/src/main/webapp/imgs/a.jpg");String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, fos, 4);System.out.println(checkCode);}/*** 输出随机验证码图片流,并返回验证码值(一般传入输出流,响应response页面端,Web项目用的较多)** @param width 图片宽度* @param height   图片高度* @param os    输出流* @param verifySize    数据长度* @return  验证码* @throws IOException*/public static String outputVerifyImage(int width, int height, OutputStream os, int verifySize) throws IOException {String verifyCode = generateVerifyCode(verifySize);outputImage(width, height, 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
<%--Created by IntelliJ IDEA.User: 19148Date: 2023/8/5Time: 10:47To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!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="/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 id="checkCodeImg" src="/brand-demo/checkCodeServlet"><a href="#" id="changeImg">看不清?</a></td></tr></table><div class="buttons"><input value="注 册" type="submit" id="reg_btn"></div><br class="clear"></form></div><script>document.getElementById("changeImg").onclick = function (){document.getElementById("checkCodeImg").src = "/brand-demo/checkCodeServlet?"+new Date().getMilliseconds();//加个参数避免同上面的路径缓存,但是这个参数在多次点击下必须要永远不一样}
</script>
</body>
</html>
  • checkCodeServlet
@WebServlet("/checkCodeServlet")
public class checkCodeServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {ServletOutputStream os = response.getOutputStream();String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, os, 4);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

在这里插入图片描述
在这里插入图片描述

2.4.4 - I 校验验证码

在这里插入图片描述
registerServlet:

@WebServlet("/registerServlet")
public class registerServlet extends HttpServlet {private UserService service = new UserService();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.获取用户和密码数据String username = request.getParameter("username");String password = request.getParameter("password");//获取用户输入的验证码String checkCode = request.getParameter("checkCode");//程序生成的验证码,从Session获取HttpSession session = request.getSession();String checkCodeGen = (String) session.getAttribute("checkCodeGen");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);//比对验证码if(!checkCodeGen.equalsIgnoreCase(checkCode)){request.setAttribute("register_msg","验证码错误");request.getRequestDispatcher("/register.jsp").forward(request,response);//不允许注册return;}}else{//注册失败request.setAttribute("register_msg","用户已经存在");request.getRequestDispatcher("/register.jsp").forward(request,response);}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

相关文章:

小黑子—JavaWeb:第五章 - JSP与会话跟踪技术

JavaWeb入门5.0 1. JSP1.1 JSP快速入门1.2 JSP原理1.3 JSP脚本1.3.1 JSP缺点 1.4 EL 表达式1.5 JSTL 标签1.5.1 JSTL 快速入门1.5.1 - I JSTL标签if1.5.1 - II JSTL标签forEach 1.6 MVC模式1.7 三层架构1.8 实现案例1.8.1 环境准备1.8.2 查询所有1.8.3 添加数据1.8.4 修改1.8.4…...

Python - 【socket】 客户端client重连处理简单示例Demo(一)

一. 前言 在Python中&#xff0c;使用socket进行网络通信时&#xff0c;如果连接断开&#xff0c;可以通过以下步骤实现重连处理 二. 示例代码 1. 定义一个函数&#xff0c;用于建立socket连接 import socketdef connect_socket(host, port):while True:try:# 建立socket连…...

Redis 基础

1.定义 Redis 是一个高性能的key-value数据库&#xff0c;key是字符串类型。 2.核心特点&#xff1a; 单进程&#xff1a; Redis的服务器程序采用的是单进程模型来处理客户端的请求。对读写时间的响 应是通过对epoll函数的包装来做到的。 3.数据类型&#xff1a; 键的类型…...

【0805作业】Linux中 AB终端通过两根有名管道进行通信聊天(半双工)

作业一&#xff1a;打开两个终端&#xff0c;要求实现AB进程对话【两根管道】 打开两个终端&#xff0c;要求实现AB进程对话 A进程先发送一句话给B进程&#xff0c;B进程接收后打印B进程再回复一句话给A进程&#xff0c;A进程接收后打印重复1.2步骤&#xff0c;当收到quit后&am…...

ruby - ckeditor 设置编辑器高度

参考&#xff1a;Blogs <% f.cktext_area :zh_content, ckeditor: { height: 1000} %>...

WMS仓库管理系统研发规划说明

01 产品背景 1.1 背景概述 aboss WMS东南亚仓库管理系统是一个基于BigSeller系统的使用基础上&#xff0c;加上多仓库的解决思路&#xff0c;解决入库业务、出库业务、仓库调拨、库存调拨和虚仓管理等功能&#xff0c;对批次管理、物料对应、库存盘点、质检管理、虚仓管理和即…...

JavaScript |(六)DOM事件 | 尚硅谷JavaScript基础实战

学习来源&#xff1a;尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版 文章目录 &#x1f4da;事件对象&#x1f4da;事件的冒泡&#x1f4da;事件的委派&#x1f4da;事件的绑定&#x1f407;赋值绑定&#x1f407;addEventListener()&#x1f407;attachEvent()&…...

实验心得,包括代码复现工作的体会

实践是检验真理的唯一标准 resnet20,cifar100. Direct training&#xff1a; 和原论文一样的参数 64.45 time step 1, Accuracy 0.5918 time step 2, Accuracy 0.6320 time step 4, Accuracy 0.6446 time step 8, Accuracy 0.6531 time step 16, Accuracy 0.6608 time ste…...

RabbitMQ(二)

二、高级特性、应用问题以及集群搭建 高级特性 1.消息的可靠性投递 在使用RabbitMQ的时候&#xff0c;作为消息发送方希望杜绝任何消息丢失或者投递失败场景。RabbitMQ 为我们提供了两种方式用来控制消息的投递可靠性模式。 rabbitMQ整个消息投递的路径为&#xff1a; produ…...

Linux软件实操

systemctl命令 Linux系统的很多内置或第三方的软件均支持使用systemctl命令控制软件(服务)的启动、停止、开机自启 systemctl start(启动) 或 stop(关闭) 或 status(查看状态) 或 enable(开启开机自启) disable(关闭开机自启) 服务名: 控制服务的状态 系统内置的服务: Netwo…...

kagNet:对常识推理的知识感知图网络 8.4+8.5

这里写目录标题 摘要介绍概述问题陈述推理流程 模式图基础概念识别模式图构造概念网通过寻找路径来匹配子图基于KG嵌入的路径修剪 知识感知图网络图卷积网络&#xff08;GCN&#xff09;关系路径编码分层注意机制 实验数据集和使用步骤比较方法KAGNET是实施细节性能比较和分析I…...

Jmeter 压测工具使用手册[详细]

1. jemter 简介 jmeter 是 apache 公司基于 java 开发的一款开源压力测试工具&#xff0c;体积小&#xff0c;功能全&#xff0c;使用方便&#xff0c;是一个比较轻量级的测试工具&#xff0c;使用起来非常简 单。因为 jmeter 是 java 开发的&#xff0c;所以运行的时候必须先…...

matlab智能算法程序包89套最新高清录制!matlab专题系列!

关于我为什么要做代码分享这件事&#xff1f; 助力科研旅程&#xff01; 面对茫茫多的文献&#xff0c;想复现却不知从何做起&#xff0c;我们通过打包成品代码&#xff0c;将过程完善&#xff0c;让您可以拿到一手的复现过程以及资料&#xff0c;从而在此基础上&#xff0c;照…...

caj文件怎么转换成pdf?了解一下这种方法

caj文件怎么转换成pdf&#xff1f;如果你曾经遇到过需要将CAJ文件转换成PDF格式的情况&#xff0c;那么你一定知道这是一件麻烦的事情。幸运的是&#xff0c;现在有许多软件和工具可以帮助你完成这项任务。下面就给大家介绍一款使用工具。 【迅捷PDF转换器】是一款功能强大的工…...

windows 同时安装 Mysql 5.7 和8.0

下载链接 https://dev.mysql.com/downloads/mysql/ 推荐下载 MSI&#xff0c;可以通过图像化界面配置 8.1 版本 安装5.7 系统安装两个MySQL 怎么访问 都是mysql&#xff0c;所以环境变量 配置&#xff0c;只能一个生效&#xff0c;生效就是谁靠前谁生效 cmd 录入 services.m…...

数字孪生的「三张皮」问题:数据隐私、安全与伦理挑战

引言 随着数字化时代的来临&#xff0c;数据成为了当今社会的宝贵资源。然而&#xff0c;数据的广泛使用也带来了一系列隐私、安全与伦理挑战。数字孪生作为一种虚拟的数字化实体&#xff0c;通过收集和分析大量数据&#xff0c;模拟和预测现实世界中的各种情境&#xff0c;为…...

Hadoop学习:深入解析MapReduce的大数据魔力(上)

Hadoop学习&#xff1a;深入解析MapReduce的大数据魔力&#xff08;上&#xff09; 前言1.MapReduce概述1.1MapReduce 定义1.2MapReduce 优缺点优点缺点 1.3MapReduce 核心思想1.4 MapReduce 进程1.5 官方WordCount源码1.6 常用数据序列化类型1.7 MapReduce 编程规范1.8 WordCo…...

MQ(一)-MQ理论与消息中间件简介

MQ理论 队列&#xff0c;是一种FIFO 先进先出的数据结构。消息&#xff1a;在不同应用程序之间传递的数据。将消息以队列的形式存储起来&#xff0c;并且在不同的应用程序之间进行传递&#xff0c;这就成了MessageQueue。MQ通常三大作用&#xff1a; 异步、解耦、限流 Spring…...

vb与EXCEL的连接

一、 VB读写EXCEL表&#xff1a; VB本身提自动化功能可以读写EXCEL表&#xff0c;其方法如下&#xff1a; 1、在工程中引用Microsoft Excel类型库&#xff1a; 从"工程"菜单中选择"引用"栏&#xff1b;选择Microsoft Excel 9.0 Object Library&#xff…...

java使用openOffice将excel转换pdf时,将所有列显示在一页

1.接上文&#xff0c;格式转换的基础问题已解决&#xff0c;但还有些细节问题需要单独处理&#xff0c;如excel转换至pdf时&#xff0c;如何将所有列显示在一页的问题&#xff0c;此问题大家都有遇到&#xff0c;解决方案也比较多&#xff0c;我也尝试过重写某类&#xff0c;来…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

链式法则中 复合函数的推导路径 多变量“信息传递路径”

非常好&#xff0c;我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题&#xff0c;统一使用 二重复合函数&#xff1a; z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y))​ 来全面说明。我们会展示其全微分形式&#xff08;偏导…...