做汽车租赁主要的网站,网络搭建基础教程,公司做网站的开支会计分录怎么做,腾讯qq会话跟踪技术#xff08;CookieSession#xff09; 注意#xff1a; HTTP协议是无状态 的#xff0c;即每次浏览器向服务器请求时#xff0c;服务器都会将该请求视为新的请求#xff0c;因此我们需要会话跟踪技术来实现会话内的数据共享 会话 当用户打开浏览器CookieSession 注意 HTTP协议是无状态 的即每次浏览器向服务器请求时服务器都会将该请求视为新的请求因此我们需要会话跟踪技术来实现会话内的数据共享 会话 当用户打开浏览器访问Web服务器资源时会话建立直到有一方断开连接时会话结束。在一次会话中可包含多次请求和响应 会话跟踪 它是一种维护浏览器状态的方法。服务器需要识别多次请求是否来自于同一个浏览器以便可以在同一次会话的多次请求中共享数据 会话跟踪技术实现的方式 客户端会话跟踪技术Cookie服务端会话跟踪技术Session
Cookie
Cookie基本使用 Cookie客户端会话跟踪技术它会将数据保存到客户端以后每次请求都携带Cookie数据进行访问 工作流程 假设有两个Servlet为A和B。此时客户端在请求AServlet数据时AServlet就会创建一个Cookie对象里面包含Cookie数据在AServlet进行响应时就会把Cookie发送给客户端客户端会将其保存到客户端的内存中当客户端在同一次会话中访问另一个BServlet时会自动携带着Cookie数据进行对BServlet的访问
发送Cookie
用到的Cookie构造器解释public Cookie(String name, String value)创建Cookie对象。name表示Cookie的名称。这个名称用于标识Cookie必须是唯一的并且不能为空。value表示Cookie的值。这个值是与Cookie名称相关联的数据。用到的Response的方法value一个String类型的参数表示Cookie的值。这个值是与Cookie名称相关联的数据。解释void addCookie(Cookie cookie)将一个 Cookie 对象添加到 HTTP 响应中。这使得服务器可以向客户端发送 Cookie客户端浏览器会接收并保存这个 Cookie并在后续请求中将其发送回服务器。 发送Cookie步骤 Step1 创建Cookie对象并设置数据Cookie cookie new Cookie(key,value);Step2 使用Response对象发送Cookie到客户端response.addCookie(cookie); 代码示例 客户端访问AServletAServlet就会创建一个Cookie对象里面包含Cookie数据在AServlet进行响应时就会把Cookie发送给客户端客户端会将其保存到客户端的内存中 package at.guigu.web.cookie;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;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, zhangsan);//2 发送Cookieresponse.addCookie(cookie);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}Tomcat运行该Web项目后截图如下
获取Cookie
用到的Request接口中的方法解释Cookie[] getCookies()获取客户端发送到服务器的所有Cookie。用到的Cookie对象的方法解释public String getName()返回Cookie的名称public String getValue()返回Cookie名对应的值 获取Cookie步骤 Step1 使用Request对象获取客户端携带的所有Cookie Cookie[] cookies request.getCookies();Step2 遍历数组获取每一个Cookie对象Step3 使用Cookie对象方法获取数据cookie.getName(); cookie.getValue(); 注意由于在实际项目中浏览器会保存很多Cookie信息所以我们需要用到条件判断来筛选出我们需要的Cookie信息 代码示例 客户端访问AServlet后此时Cookie在客户端内存中访问另一个BServletBServlet获取客户端保存的Cookie package at.guigu.web.cookie;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;WebServlet(/bServlet)
public class BServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取Cookie//1 通过request对象获取Cookie数组Cookie[] cookies request.getCookies();//2 遍历Cookie并获取Cookie的键值对for (Cookie cookie : cookies) {//3 通过Cookie对象获取AServlet发送的Cookie数据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);}
}Tomcat运行该Web项目后运行截图如下
Cookie原理 Cookie的实现是基于HTTP协议的 响应头set-cookie 发送Cookie用到响应头 请求头cookie 获取Cookie用到请求头 工作流程解释 AServlet发送Cookie AServlet中创建了Cookie数据Tomcat会将该Cookie对象响应给客户端浏览器由于Tomcat是基于Http协议做出响应的所以发送给客户端的是Http协议的响应数据当Tomcat发现服务端要发送Cookie给客户端浏览器时会在响应数据中给Cookie加上一个响应头即set-cookie然后将其发送给客户端浏览器客户端接收到该响应数据后通过响应头set-cookie知道服务端发送的是Cookie则会对其进行解析解析后则会拿到usernamezhangsan这个数据并将其存储到客户端的内存中BServlet接收Cookie 当客户端携带Cookie数据来访问BServlet时浏览器会自动为Cookie设置一个请求头cookie然后将其发送给BServlet然后BServlet即可通过对应的方法来获取到客户端发送到服务器的所有Cookie 代码示例 代码示例即为发送Cookie和获取Cookie的代码示例运行截图如下
Cookie存活时间
Cookie类中的方法解释public void setMaxAge(int seconds)设置 Cookie 的最大存活时间。seconds为秒数 默认情况下 Cookie存储在浏览器内存中当浏览器被关闭时内存释放则Cookie被销毁 即BServlet能访问到AServlet发送给浏览器的Cookie是因为浏览器在发送请求给AServlet后并没有关闭浏览器如果浏览器在发送请求给AServlet后关闭了浏览器此时浏览器发送请求给BServlet则BServlet接收不到AServlet发送给浏览器的Cookie除非AServlet设置Cookie存活时间。 可利用setMaxAge(int seconds)方法来设置Cookie存活时间 正数 将Cooke写入浏览器所在电脑的硬盘持久化存储但到时间会自动删除负数 默认值Cookie在当前浏览器内存中当浏览器关闭时Cookie会被立即销毁零 删除对应Cookie 代码示例 AServlet代码如下 package at.guigu.web.cookie;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;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, zhangsan);//设置Cookie存活时间--此处设置为2天cookie.setMaxAge(60*60*24*2);//2 发送Cookieresponse.addCookie(cookie);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}BServlet代码详见获取CookieTomcat运行该Web项目后运行步骤截图如下所示 Step1访问AServlet后关闭浏览器 Step2重新打开一个浏览器访问BServlet访问后服务端显示出Cookie
Cookie存储中文 Cookie默认情况下不能存储中文若存储则会报错 AServlet的Cookie存储中文方法利用URL编码进行转码 Step1单独设置Cookie构造器的第二个参数value的值 Step2将value进行转码value URLEncoder.encode(value,UTF-8); Step3创建Cookie对象Cookie cookie new Cookie(key, value) AServlet代码示例如下 package at.guigu.web.cookie;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.net.URLEncoder;WebServlet(/aServlet)
public class AServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//发送Cookie//1 创建Cookie对象并设置数据String value 张三;value URLEncoder.encode(value, UTF-8);Cookie cookie new Cookie(username, value);//设置Cookie存活时间--此处设置为2天cookie.setMaxAge(60*60*24*2);//2 发送Cookieresponse.addCookie(cookie);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}BServlet获取Cookie中的中文的方法利用URL编码进行解码 Step1首先获取到对应的value值 Step2将value值利用URLDecoder.decode(value, UTF-8);方法进行解码 BServlet代码示例如下 package at.guigu.web.cookie;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;WebServlet(/bServlet)
public class BServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取Cookie//1 通过request对象获取Cookie数组Cookie[] cookies request.getCookies();//2 遍历Cookie并获取Cookie的键值对for (Cookie cookie : cookies) {//3 通过Cookie对象获取AServlet发送的Cookie数据String name cookie.getName();if (username.equals(name)) {String value cookie.getValue();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);}
}Session Session服务端会话跟踪技术它会将数据保存到服务端 JavaEE提供了HttpSession接口用来实现一次会话的多次请求间的数据共享功能 工作流程 假设有两个Servlet为A和B。此时客户端在请求AServlet数据时AServlet就会创建一个Cookie对象里面包含Cookie数据在AServlet进行响应时就会把Cookie发送给客户端客户端会将其保存到客户端的内存中当客户端在同一次会话中访问另一个BServlet时会自动携带着Cookie数据进行对BServlet的访问这个过程就会造成Cookie暴露在网络中就会很不安全为了解决该问题就有了SessionA和B两个Servlet可以创建同一个Session对象我们可以通过AServlet向Session对象中存入数据然后BServlet也可以通过Session对象来获取存入的数据以上步骤即可实现一次会话中两个请求的数据共享 注意一次会话的多次请求之间使用的是同一个Session对象
Session基本使用
用到的Request接口的方法解释HttpSession getSession();获取当前会话如果没有会话则创建一个新的会话Session对象用到的Session对象的方法解释void setAttribute(String name, Object o)存储数据到session域中Object getAttribute(String name)根据key获取对应的值void removeAttribute(String name)根据key删除对应的键值对 使用步骤 Step1通过Request对象来获取Session对象即HttpSession session request.getSession();Step2利用Session对象相关方法执行对应的功能 代码示例 ASessionServlet类代码 package at.guigu.web.session;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;WebServlet(/aSessionServlet)
public class ASessionServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//向Session中存储数据//1 获取Session对象HttpSession session request.getSession();//2 存储数据session.setAttribute(username, zhangsan);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}BSessionServlet类代码 package at.guigu.web.session;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 javax.servlet.http.HttpSession;
import java.io.IOException;WebServlet(/bSessionServlet)
public class BSessionServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//从Session中获取数据//1 获取Session对象HttpSession session request.getSession();//2 获取对应数据String username (String) session.getAttribute(username);System.out.println(username);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}运行截图如下
Session原理 Session是基于Cookie实现的 工作流程解释 浏览器在一次会话的第一次请求中服务端ASessionServlet会首次创建一个Session对象并会自动会该对象分配一个唯一标识的ID在向Session域中存储数据后Tomcat会给浏览器做出响应在做出响应的这个过程中会识别到Session对象当识别到Session对象时会自动将该Session对象对应的ID作为Cookie传给客户端浏览器即set-cookie:JSESSIONIDID值当浏览器第二次请求时会将该Cookie即cookie:JSESSIONIDID值传给对应的服务端BSessionServlet当BSessionServlet接收到该Cookie后会自动根据ID值来找到对应的Session对象以上步骤即可保证在一次会话的多次请求间服务器使用的是同一个Session对象 代码示例 代码示例即为Session基本使用那一部分内容中的代码示例访问服务端ASessionServlet后再次访问服务端BSessionServlet的运行截图分别如图一和图二所示
Session钝化、活化 服务器 正常 关闭或 正常 重启后Session中的数据依然存在前提是浏览器处于一次会话 钝化在服务器正常关闭后Tomcat会自动将Session数据写入到硬盘的文件中活化再次启动服务器后Tomcat会自动将其重新加载到Session中 若浏览器处于不同次会话则重新访问服务器时服务器会重新创建一次Session对象而不是原来的Session对象即获得的Session不会是同一个Session详见以下示例 ASessionServlet代码如下 package at.guigu.web.session;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;WebServlet(/aSessionServlet)
public class ASessionServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//向Session中存储数据//1 获取Session对象HttpSession session request.getSession();//2 存储数据session.setAttribute(username, zhangsan);System.out.println(session);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}运行截图如下由图可知两次获得的Session对象不是同一个 浏览器多次请求可获得同一个Session的情景即Session共享的条件 浏览器处于同一次会话的多个请求 若浏览器完全关闭就不属于同一次会话此时服务端若正常关闭或正常重启只要浏览器处于同一次会话就仍可获得同一个Session对象
Session存活时间及销毁 默认情况下若浏览器无任何操作则会在30分钟后自动销毁Session对象 更改自动销毁时间的方法 在web.xml文件中的web-app标签体内加入以下标签代码 session-configsession-timeout自己要配置的时间以分钟为单位/session-timeout
/session-config在Session自动销毁之前就销毁Session对象的方法 在浏览器请求的服务端此处以第二次请求的服务端BSessionServlet为例调用Session对象的invalidate()方法代码如下所示 销毁之后就无法获取Session中的任何数据了 package at.guigu.web.session;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 javax.servlet.http.HttpSession;
import java.io.IOException;WebServlet(/bSessionServlet)
public class BSessionServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//从Session中获取数据//1 获取Session对象HttpSession session request.getSession();//销毁Session对象session.invalidate();//2 获取对应数据String username (String) session.getAttribute(username);System.out.println(username);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}Cookie和Session的异同及应用场景 相同点 都是来完成一次会话内多次请求见的数据共享的 不同点 存储位置Cookie 是将数据存储在客户端Session 将数据存储在服务端安全性Cookie不安全Session安全数据大小Cookie最大3KBSession无大小限制存储时间Cookie可以通过setMaxAge()长期存储Session默认30分钟服务器性能Cookie不占服务器资源Session占用服务器资源 应用场景 购物车:使用Cookie来存储 记住我功能:使用Cookie来存储 比如记住用户名和密码这些数据都是需要安全的但是又由于Session只能短期存储无法长期存储所以只能用Cookie 以登录用户的名称展示:使用Session来存储 验证码:使用session来存储 结论 Cookie是用来保证用户在未登录情况下的身份识别Session是用来保存用户登录后的数据
会话跟踪技术登录案例
注意该案例已上传到Gitee可自行下载 https://gitee.com/cgrs572/cookie-session-demo.git
需求说明 环境准备 创建新的Web项目BrandDemo引入坐标在pom.xml文件中引入坐标依赖并配置Tomcat可详见Tomcat部分 需要的坐标依赖有mybatis、mysql驱动、servlet、jsp、jstl 需要的插件有Tomcat插件 完整pom.xml文件如下 project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsdmodelVersion4.0.0/modelVersiongroupIdorg.example/groupIdartifactIdBrandDemo/artifactIdpackagingwar/packagingversion1.0-SNAPSHOT/versionnameBrandDemo Maven Webapp/nameurlhttp://maven.apache.org/urldependenciesdependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion3.8.1/versionscopetest/scope/dependency!--MyBatis依赖--dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.16/version/dependency!--mysql驱动--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.33/version/dependency!--Servlet依赖--dependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopeprovided/scope!--依赖范围关键字provided:在编译环境和测试环境有效但在真正运行时就不会在使用该jar包--/dependency!--JSP依赖--dependencygroupIdjavax.servlet.jsp/groupIdartifactIdjsp-api/artifactIdversion2.2/versionscopeprovided/scope/dependency!--jstl依赖--dependencygroupIdjstl/groupIdartifactIdjstl/artifactIdversion1.2/version/dependencydependencygroupIdtaglibs/groupIdartifactIdstandard/artifactIdversion1.1.2/version/dependency/dependenciesbuildfinalNameBrandDemo/finalNameplugins!-- Tomcat插件 --plugingroupIdorg.apache.tomcat.maven/groupIdartifactIdtomcat7-maven-plugin/artifactIdversion2.2/version/plugin/plugins/build
/project创建三层架构包结构 创建数据库表tb_user并使IDEA与数据库建立连接SQL代码如下 DROP TABLE IF EXISTS tb_user;
#创建表
CREATE TABLE tb_user (id INT PRIMARY KEY AUTO_INCREMENT,username varchar(20),password varchar(20),gender char(1)L,addr varchar(30),
);#向表中添加数据
INSERT INTO tb_user VALUES (1, zhangsan, 123, 男, 北京);
INSERT INTO tb_user VALUES (2, 李四, 234, 女, 天津);
INSERT INTO tb_user VALUES (3, 王五, 11, 男, 西安);创建实体类User此为Pojo类 存放对数据库中数据封装的对象代码如下 package at.guigu.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;}Overridepublic String toString() {return User{ id id , username username \ , password password \ };}
}MyBrtis基础环境配置 在mapper包下创建UserMapper接口 在项目的源代码配置文件目录即main包下的resources目录下创建多层目录多层目录对应Mapper接口所在的多层包然后再该包中创建UserMapper.xmlSQL映射文件基本代码如下 ?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd!--namespace名称空间
--
mapper namespaceat.guigu.mapper.UserMapper!--由于数据库中的字段名与pojo包下User类中的属性名一致所以不需结果映射--/mapper在项目的源代码配置文件目录即main包下的resources目录下创建MyBatis核心配置文件mybatis-config.xml代码如下 ?xml version1.0 encodingUTF-8 ?
!DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttps://mybatis.org/dtd/mybatis-3-config.dtd
configuration!--设置别名--typeAliasespackage nameat.guigu.pojo//typeAliasesenvironments defaultdevelopmentenvironment iddevelopmenttransactionManager typeJDBC/dataSource typePOOLED!--数据库 连接信息--property namedriver valuecom.mysql.cj.jdbc.Driver/property nameurl valuejdbc:mysql://localhost:3306/mybatis?useUnicodetrueamp;characterEncodingutf-8amp;useSSLfalseamp;serverTimezoneAsia/Shanghai/property nameusername valueroot/property namepassword value123456//dataSource/environment/environmentsmappers!--加载SQL映射文件传入sql映射文件的路径--
!-- mapper resourceat/guigu/mapper/BrandMapper.xml/--package nameat.guigu.mapper//mappers
/configuration将JSP案例中的所有代码均移动到该Web项目下使该登录案例登录成功后即为JSP案例中的页面具体截图详见后续
用户登录 解释若登录成功则进入用户个人主页若登录失败则显示出对应错误之处 要完成该问则需满足三层架构各层需要做的工作如下所示 Dao层/Map层 Step1 UserMapper接口中写入查询所有数据的方法 package at.guigu.mapper;import at.guigu.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);
}Step2 在对应的SQL映射文件UserMapper.xml中写入SQL语句 ?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd!--namespace名称空间
--
mapper namespaceat.guigu.mapper.UserMapper!--由于数据库中的字段名与pojo包下User类中的属性名一致所以不需结果映射--select idselect resultTypeuserselect * from tb_userwhere username#{username} and password#{password};/select
/mapperService层 由于Service层中的类均需要调用Mapper接口中的方法那么该层中的类就都需要载核心配置文件来获取SqlSessionFactorySQL连接工厂对象所以就可以将SqlSessionFactory封装为一个工具类。所以在完善Service层之前需要先在util包下将工具类SqlSessionFactoryUtils创建好代码如下 package at.guigu.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 {//配置mybatis-config.xml文件路径。注意若该文件直接在resources目录下则直接写文件名即可String resource mybatis-config.xml;//利用Resources类中的静态方法将配置文件加载到内存InputStream inputStream Resources.getResourceAsStream(resource);//获取SqlSessionFactory对象sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);} catch (IOException e) {e.printStackTrace();}}public static SqlSessionFactory getSqlSessionFactory() {return sqlSessionFactory;}
}Step1 在service包下创建UserService类来调用mapper包下的UserMapper接口中的select方法代码如下 注意获取SqlSessionFactory对象的代码放在了成员变量的位置这样所有方法可共用该对象并不需要重复获取 package at.guigu.service;import at.guigu.mapper.UserMapper;
import at.guigu.pojo.User;
import at.guigu.util.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;import java.util.List;
public class UserService {//1 获取SqlSessionFactory对象SqlSessionFactory sqlSessionFactory SqlSessionFactoryUtils.getSqlSessionFactory();/***登录方法* param username* param password* return*/public User login(String username, String password) {//2 获取SqlSession对象执行SQL语句//2.1 获取SqlSession对象SqlSession sqlSession sqlSessionFactory.openSession();//2.2 获取Mapper接口UserMapper的代理对象UserMapper userMapper sqlSession.getMapper(UserMapper.class);//2.3 执行sql语句User user userMapper.select(username, password);//释放资源sqlSession.close();return user;}
}Web层 Step1由于Tmcat运行该项目后直接是用户登录页面所以应该有个login.jsp登录页面代码如下所示 注意博主将无关修饰均已去除只有个简单的静态登录页面 % taglib prefixc urihttp://java.sun.com/jsp/jstl/core %
% page contentTypetext/html;charsetUTF-8 languagejava isELIgnoredfalse %
htmlheadtitleTitle/title/headbodyform action/CookieSessionDemo/loginServlet methodposth1登录系统/h1用户名input nameusername typetextbr密码input namepassword typepasswordbr记住账号input nameremember typecheckboxbrinput value登录 typesubmit!--这里提前写了一下注册的跳转链接后面我们会把这个页面也写完--a href/CookieSessionDemo/register.jsp没有账号/a/form/body
/html其运行截图如下 Step2创建LoginServlet类且代码如下 注意创建一个私有的UserService对象应将其放在成员变量的位置因为对于大工程来说可能会多次用到Service对象若登录成功则跳转到查询所有品牌的页面且该页面会欢迎登录的用户若登陆失败则重新返回到用户登录页面即login.jsp且该页面给出提示信息 package at.guigu.web;import at.guigu.pojo.User;
import at.guigu.service.BrandService;
import at.guigu.service.UserService;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;WebServlet(/loginServlet)
public class LoginServlet extends HttpServlet {//1 创建一个私有的UserService对象private UserService userService new UserService();Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//2 获取用户名和密码String username request.getParameter(username);String password request.getParameter(password);//3 调用Service查询用户名和密码是否正确User user userService.login(username, password);if (user ! null) {//用户登陆成功//1 将登陆成功后的User对象存储到Session中HttpSession session request.getSession();session.setAttribute(user, user);//2 跳转到查询所有页面//注意:由于登录界面和查询所有页面的请求没有资源共享所以使用重定向//动态获取虚拟目录String contextPath request.getContextPath();response.sendRedirect(contextPath /selectAllServlet);} else {//用户登录失败//将错误信息存储到request域中request.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);}
}若用户登录成功则跳转到查询所有商品页面且该页面会欢迎登录的用户所以brand.jsp代码如下 % taglib prefixc urihttp://java.sun.com/jsp/jstl/core %
% page contentTypetext/html;charsetUTF-8 languagejava isELIgnoredfalse %
htmlheadtitleTitle/title/headbodyh1${user.username}欢迎您/h1input typebutton value新增 idaddbrhrtable border1 cellspacing0trth序号/thth品牌名称/thth企业名称/thth排序/thth品牌介绍/thth状态/thth操作/th/trc:forEach items${brands} varbrand varStatusxuhaotr aligncentertd${xuhao.count}/tdtd${brand.brandName}/tdtd${brand.companyName}/tdtd${brand.ordered}/tdtd${brand.description}/tdc:choosec:when test${brand.status1}td启用/td/c:whenc:otherwisetd禁用/td/c:otherwise/c:choosetda href/CookieSessionDemo/selectByIdServlet?id${brand.id}修改/a a href#删除/a/td/tr/c:forEach/tablescriptdocument.getElementById(add).onclick function () {//addBrand.jsp的路径location.href /CookieSessionDemo/addBrand.jsp;}/script/body
/html若登陆失败则重新返回到用户登录页面即login.jsp且该页面给出提示信息所以login.jsp更改后的代码如下 % taglib prefixc urihttp://java.sun.com/jsp/jstl/core %
% page contentTypetext/html;charsetUTF-8 languagejava isELIgnoredfalse %
htmlheadtitleLogin/title/headbodyform action/CookieSessionDemo/loginServlet methodposth1登录系统/h1%--提示错误信息代码--%div${login_msg}/div用户名input nameusername typetextbr密码input namepassword typepasswordbr记住账号input nameremember typecheckboxbrinput value登录 typesubmit!--这里提前写了一下注册的跳转链接后面我们会把这个页面也写完--a href/CookieSessionDemo/register.jsp没有账号/a/form/body
/htmlTomcat运行该Web项目后截图如下所示 登录成功界面 登陆失败界面
记住用户——写Cookie 解释若用户勾选“记住账号”则下次访问登录页面时会 自动填充 用户名和密码 过程 将用户名和密码写入到Cookie中并且进行持久化存储Cookie下次访问浏览器时会自动携带Cookie在页面获取到Cookie数据后会将用户名和密码自动设置到用户名和密码框中 写Cookie的条件 用户登录成功用户勾选“记住账号”复选框 需要对Web层进行更改如下图所示 Web层 Step1login.jsp代码如下 在复选框中加入属性value1这样只要复选框被勾选服务端就能通过获取到该复选框数据来判断是否用户“记住账号” % taglib prefixc urihttp://java.sun.com/jsp/jstl/core %
% page contentTypetext/html;charsetUTF-8 languagejava isELIgnoredfalse %
htmlheadtitleLogin/title/headbodyform action/CookieSessionDemo/loginServlet methodposth1登录系统/h1%--提示错误信息--%div${login_msg}/div用户名input nameusername typetextbr密码input namepassword typepasswordbr记住账号input nameremember typecheckbox value1brinput value登录 typesubmit!--这里提前写了一下注册的跳转链接后面我们会把这个页面也写完--a href/CookieSessionDemo/register.jsp没有账号/a/form/body
/htmlStep2LoginServlet类代码如下 package at.guigu.web;import at.guigu.pojo.User;
import at.guigu.service.BrandService;
import at.guigu.service.UserService;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;WebServlet(/loginServlet)
public class LoginServlet extends HttpServlet {//1 创建一个私有的UserService对象private UserService userService new UserService();Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//2 获取用户名和密码以及获取复选框数据String username request.getParameter(username);String password request.getParameter(password);// 获取复选框数据String remember request.getParameter(remember);//3 调用Service查询用户名和密码是否正确User user userService.login(username, password);if (user ! null) {//用户登陆成功//1 判断用户是否勾选复选框即是否勾选记住账号if (1.equals(remember)) {//1.1 创建Cookie对象Cookie c_username new Cookie(username, username);Cookie c_password new Cookie(password, password);//1.2 设置Cookie存活时间——均设置为7天c_username.setMaxAge(60 * 60 * 24 * 7);c_password.setMaxAge(60 * 60 * 24 * 7);//1.3 将其发送到客户端response.addCookie(c_username);response.addCookie(c_password);}//2 将登陆成功后的User对象存储到Session中HttpSession session request.getSession();session.setAttribute(user, user);//3 跳转到查询所有页面//注意:由于登录界面和查询所有页面的请求没有资源共享所以使用重定向//动态获取虚拟目录String contextPath request.getContextPath();response.sendRedirect(contextPath /selectAllServlet);} else {//用户登录失败//将错误信息存储到request域中request.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);}
}Tomcat运行成功后截图如下 Step1输入用户名和密码并勾选“记住账号”后单击登录 Step2登录成功会进入到查询所有商品的页面。由于是通过LoginServlet类向客户端服务器发送的响应所以需要在开发者工具中找到loginServlet打开后如图所示
记住用户——获取Cookie 解释勾选“记住账号”后在下一次打开浏览器登录时会自动填充用户名和密码 用户名和密码的获取是在登录界面login.jsp的代码中直接获取 此处用到EL表达式 并填写到对应的用户名和密码框中 EL表达式获取到Cookie的代码方式为 EL代码解释${cookie.key.value}通过键key获取到对应的键值。key指存储在Cookie中自己所设置的键的名称 login.jsp代码如下 % taglib prefixc urihttp://java.sun.com/jsp/jstl/core %
% page contentTypetext/html;charsetUTF-8 languagejava isELIgnoredfalse %
htmlheadtitleLogin/title/headbodyform action/CookieSessionDemo/loginServlet methodposth1登录系统/h1%--提示错误信息--%div${login_msg}/div用户名input nameusername typetext value${cookie.username.value}br密码input namepassword typepassword value${cookie.password.value}br记住账号input nameremember typecheckbox value1brinput value登录 typesubmit!--这里提前写了一下注册的跳转链接后面我们会把这个页面也写完--a href/CookieSessionDemo/register.jsp没有账号/a/form/body
/htmlTomcat运行该Web项目后只要在输入用户名和密码之后勾选“记住账号”则在下一次打开浏览器登录时会自动填充用户名和密码如图所示
用户注册 解释将用户信息保存到数据库使用户下次能够登录 注册涉及的功能 注册功能保存用户信息至数据库验证码功能 展示验证码展示验证码图片并且可以点击切换校验验证码验证码填写不正确则注册失败 要完成该问则需满足三层架构各层需要做的工作如下所示 Dao层/Map层 Step1 UserMapper接口中写入对应的方法 package at.guigu.mapper;import at.guigu.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);/*** 通过用户名查询用户* param username* return*///Select(select * from tb_user where username#{username})User selectByUsername(String username);/*** 注册用户* param user*///Select(insert into tb_user(username, password) values (#{username}, #{password}))void add(User user);
}Step2在对应的SQL映射文件UserMapper.xml中写入SQL语句 ?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd!--namespace名称空间
--
mapper namespaceat.guigu.mapper.UserMapper!--由于数据库中的字段名与pojo包下User类中的属性名一致所以不需结果映射--select idselect resultTypeuserselect * from tb_userwhere username#{username} and password#{password};/selectselect idselectByUsername resultTypeat.guigu.pojo.Userselect * from tb_user where username#{username};/selectinsert idaddinsert into tb_user(username, password) values (#{username}, #{password});/insert
/mapperService层 工具类SqlSessionFactoryUtils代码省略详见用户登录中的SqlSessionFactoryUtils代码 Step1 在service包下创建UserService类来调用mapper包下的UserMapper接口中的方法代码如下 package at.guigu.service;import at.guigu.mapper.UserMapper;
import at.guigu.pojo.User;
import at.guigu.util.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;import java.util.List;
public class UserService {//1 获取SqlSessionFactory对象SqlSessionFactory sqlSessionFactory SqlSessionFactoryUtils.getSqlSessionFactory();/***登录方法* param username* param password* return*/public User login(String username, String password) {//2 获取SqlSession对象执行SQL语句//2.1 获取SqlSession对象SqlSession sqlSession sqlSessionFactory.openSession();//2.2 获取Mapper接口UserMapper的代理对象UserMapper userMapper sqlSession.getMapper(UserMapper.class);//2.3 执行sql语句User user userMapper.select(username, password);//释放资源sqlSession.close();return user;}/*** 注册功能* param user* return*/public boolean register(User user) {//2 获取SqlSession对象执行SQL语句//2.1 获取SqlSession对象SqlSession sqlSession sqlSessionFactory.openSession();//2.2 获取Mapper接口UserMapper的代理对象UserMapper userMapper sqlSession.getMapper(UserMapper.class);//3 判断用户名是否存在若不存在则可添加用户User u userMapper.selectByUsername(user.getUsername());if (u null) {//用户名不存在,注册//4 执行sql语句userMapper.add(user);//5 注意增删改的SQL语句需要手动提交事务让其生效sqlSession.commit();}//释放资源sqlSession.close();//当u!null时代表用户名存在会返回false反之会返回truereturn unull;}
}Web层 Step1在Web项目核心目录下创建register.jsp且代码如下 %--Created by IntelliJ IDEA.User: 10195Date: 2024/7/2Time: 13:54To change this template use File | Settings | File Templates.
--%
% taglib prefixc urihttp://java.sun.com/jsp/jstl/core %
% page contentTypetext/html;charsetUTF-8 languagejava isELIgnoredfalse %
htmlheadtitleTitle/title/headbodyform action/CookieSessionDemo/registerServlet methodposth1欢迎注册/h1!--已有账号的话就跳转至登录页面--已有账号a hreflogin.jsp点击登录/abr%--提示错误信息--%div${register_msg}/div用户名input nameusername typetextbr密码input namepassword typepasswordbrinput value注册 typesubmit/form/body
/htmlStep2创建RegisterServlet类且代码如下 package at.guigu.web;import at.guigu.pojo.User;
import at.guigu.service.UserService;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;WebServlet(/registerServlet)
public class RegisterServlet extends HttpServlet {//1 创建一个私有的UserService对象private UserService userService new UserService();Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//2 接收用户信息获取用户名和密码以及获取复选框数据String username request.getParameter(username);String password request.getParameter(password);User user new User();user.setUsername(username);user.setPassword(password);//3 调用Service注册用户Boolean flag userService.register(user);//4 判断是否注册成功if (flag) {//注册成功request.setAttribute(register_msg, 注册成功请登录);//跳回到用户登录页面即login.jsprequest.getRequestDispatcher(/login.jsp).forward(request, response);} else {//注册失败//将错误信息存储到request域中request.setAttribute(register_msg, 用户名重复);//跳回到用户登录页面即login.jsprequest.getRequestDispatcher(/register.jsp).forward(request, response);}}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}Tomcat运行该Web项目后运行截图如下所示 单击“没有账号”跳转到注册页面 注册失败注册时若用户名已存在则会提示 注册城成功后会自动跳转到登录界面并提示注册成功
验证码展示 解释展示验证码图片并可以通过单击切换验证码 验证码原理它其实就是Java代码生成的图片 验证码作用防止机器自动注册以此来攻击服务器 实现流程 前端发送请求给CheckCodeServletCheckCodeServlet接收到请求后生成验证码图片将图片用Reponse对象的输出流写回到前端 Service层 验证码工具类CheckCodeUtil代码如下 package at.guigu.util;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
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 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 width* param height* param outputFile* param verifySize* return* throws IOException*/public static String outputVerifyImage(int width, int height, File outputFile, int verifySize) throws IOException {String verifyCode generateVerifyCode(verifySize);outputImage(width, height, outputFile, verifyCode);return verifyCode;}/*** 生成指定验证码图像文件** param width* param height* param outputFile* param code* throws IOException*/public static void outputImage(int width, int height, 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(width, height, 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);}}}
}Web层 Step1register.jsp文件代码更改如下 注意 验证码图片路径为CheckCodeServlet给图片绑定一个单击事件只要单击图片就会重新生成验证码给看不清绑定一个单击事件只要单击看不清就会重新生成验证码 给看不清绑定的单击事件对应的图片路径要加上一个时间戳原因是在单击看不清之前所生成的验证码数据图片已经被浏览器缓存所以若不加时间戳则单击看不清后验证码数据不会改变使用的是被缓存的验证码数据图片 % taglib prefixc urihttp://java.sun.com/jsp/jstl/core %
% page contentTypetext/html;charsetUTF-8 languagejava isELIgnoredfalse %
htmlheadtitleTitle/title/headbodyform action/CookieSessionDemo/registerServlet methodposth1欢迎注册/h1!--已有账号的话就跳转至登录页面--已有账号a hreflogin.jsp点击登录/abr%--提示错误信息--%div${register_msg}/div用户名input nameusername typetextbr密码input namepassword typepasswordbr验证码input namecheckCode typetextimg idcheckCodeImg src/CookieSessionDemo/checkCodeServleta href# idcheckImg看不清/ainput value注册 typesubmit/formscriptdocument.getElementById(checkCodeImg).onclick function () {//路径后面加一个时间戳能保证生成的图片永远不一样避免浏览器缓存静态资源document.getElementById(checkCodeImg).src /CookieSessionDemo/checkCodeServlet? new Date().getMilliseconds();}document.getElementById(checkImg).onclick function () {//路径后面加一个时间戳能保证生成的图片永远不一样避免浏览器缓存静态资源document.getElementById(checkCodeImg).src /CookieSessionDemo/checkCodeServlet? new Date().getMilliseconds();}/script/body
/htmlStep2创建CheckCodeServlet类且代码如下 package at.guigu.web;import at.guigu.util.CheckCodeUtil;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.OutputStream;WebServlet(/checkCodeServlet)
public class CheckCodeServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取字节输出流ServletOutputStream sos response.getOutputStream();//获取验证码字符串数据String checkCode CheckCodeUtil.outputVerifyImage(100, 50, sos, 4);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}Tomcat运行该Web项目运行截图如下
验证码校验 解释 判断程序生成的验证码和用户输入的验证码是否一样若不一样则阻止注册验证码图片和提交注册表单是两次请求所以要将程序生成的验证码存入Session中 Web层工作流程如下 Web层 Step1CheckCodeServlet文件代码更改如下 package at.guigu.web;import at.guigu.util.CheckCodeUtil;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.OutputStream;WebServlet(/checkCodeServlet)
public class CheckCodeServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1 生成验证码//获取字节输出流ServletOutputStream sos response.getOutputStream();//调用工具类获取验证码字符串数据并生成验证码数据图片String checkCode CheckCodeUtil.outputVerifyImage(100, 50, sos, 4);//2 将系统自动生成的验证码字符串存入SessionHttpSession session request.getSession();session.setAttribute(checkCodeGen, checkCode);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}Step2RegisterServlet文件代码更改如下 package at.guigu.web;import at.guigu.pojo.User;
import at.guigu.service.UserService;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;WebServlet(/registerServlet)
public class RegisterServlet extends HttpServlet {//1 创建一个私有的UserService对象private UserService userService new UserService();Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//2 接收用户信息获取用户名和密码以及获取复选框数据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);//获取程序自动生成的验证码HttpSession session request.getSession();String checkCodeGen (String) session.getAttribute(checkCodeGen);//验证验证码是否正确此处忽略大小写if (!checkCodeGen.equalsIgnoreCase(checkCode)) {//如果不一样则不允许注册即注册失败//将错误信息存储到request域中request.setAttribute(register_msg, 验证码错误请重新输入);//跳回到用户登录页面即login.jsprequest.getRequestDispatcher(/register.jsp).forward(request, response);return;//结束执行本java文件中的后续代码}//3 调用Service注册用户Boolean flag userService.register(user);//4 判断是否注册成功if (flag) {//注册成功request.setAttribute(login_msg, 注册成功请登录);//跳回到用户登录页面即login.jsprequest.getRequestDispatcher(/login.jsp).forward(request, response);} else {//注册失败//将错误信息存储到request域中request.setAttribute(register_msg, 用户名重复);//跳回到用户登录页面即login.jsprequest.getRequestDispatcher(/register.jsp).forward(request, response);}}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}Tomcat运行该Web项目运行截图如下 验证码错误 验证码正确