【途牛旅游项目】02 - 登录功能实现 - 验证码功能 - ajax实现登录

傷城~ 2022-12-12 12:29 289阅读 0赞

文章目录

    • 登录功能分析图解
    • 最终实现截图
    • 实现登录功能
        1. 创建测试类
        1. 创建业务层UserService
        1. 创建实体类 - User用户类和Msg错误提示类
        1. 创建dao层
        1. 创建dao的映射文件
        1. 创建属性文件,连接数据库db.properties
        1. 编写日志配置log4j2.xml
        1. 配置Spring核心配置文件applicationContext.xml
        1. 创建获取class类的工具类GetDaoUtils
        1. 运行测试类,测试逻辑是否有问题
        1. 编写随机生成验证码的业务逻辑类
        1. 编写图片验证码的servlet
        1. 登录servlet
        1. 编写filter,全局编码解决
        1. 编写页面jsp,点击验证码进行图片更换
        1. aJax实现异步登录,并判断输入是否合法,防止非法注入
        1. 运行结果

登录功能分析图解

在这里插入图片描述

最终实现截图

在这里插入图片描述

实现登录功能

1. 创建测试类

  1. //测试user业务层
  2. public class TestUserService {
  3. //测试登录
  4. @Test
  5. public void test01(){
  6. UserService userService = new UserService();
  7. //创建user数据
  8. User user = new User();
  9. user.setUsername("861221293");
  10. user.setPassword("ABC123456");
  11. //user.setStatus("Y");//用户激活
  12. //测试登录
  13. int code = userService.login(user);
  14. if(code == 1){
  15. System.out.println("登录成功");
  16. }else if(code == -1){
  17. System.out.println("用户名或密码错误");
  18. }else if(code == -2){
  19. System.out.println("用户未激活");
  20. }
  21. }
  22. }

2. 创建业务层UserService

  1. //user业务层
  2. public class UserService {
  3. private static UserDao userDao = null;
  4. //登录用户
  5. public int login(User user) {
  6. userDao = GetDaoUtils.getMapper(UserDao.class);
  7. User u = userDao.getUserByUsernamePassword(user);
  8. if(u == null){
  9. return -1; //账号密码匹配找不到
  10. }else {
  11. //判断用户user是否激活
  12. if(u.getStatus().equals("Y")){
  13. return 1; //账号密码正确,且已经激活
  14. }else {
  15. return -2; //账号未激活
  16. }
  17. }
  18. }
  19. }

3. 创建实体类 - User用户类和Msg错误提示类

  1. //User类
  2. public class User {
  3. private int uid;
  4. private String username; //登录用户名
  5. private String password; //密码
  6. private Date birthday; //生日
  7. private String name; //昵称
  8. private String sex; //性别
  9. private String telephone; //电话号码
  10. private String email; //邮箱
  11. private String status; //激活状态
  12. private String code; //激活码(UUID)
  13. //省略getter/setter方法
  14. }
  15. //Msg信息提示类
  16. public class Msg {
  17. private int code;
  18. private Object data;
  19. //省略getter/setter方法
  20. }

4. 创建dao层

  1. public interface UserDao {
  2. // 通过usernmae和password查询用户
  3. public User getUserByUsernamePassword(User user);
  4. }

5. 创建dao的映射文件

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.xgf.dao.UserDao">
  4. <select id="getUserByUsernamePassword" parameterType="com.xgf.bean.User" resultType="com.xgf.bean.User">
  5. select uid,username,password,name,birthday,sex,telephone,email,status,code
  6. from tab_user
  7. where username = #{username} and password = #{password}
  8. </select>
  9. </mapper>

6. 创建属性文件,连接数据库db.properties

  1. #mysql jdbc 属性文件里面不能有分号
  2. jdbc.driver = com.mysql.jdbc.Driver
  3. jdbc.url = jdbc:mysql://localhost:3306/travelnetwork?useUnicode=true&characterEncoding=UTF-8&useSSL=false
  4. jdbc.username = root
  5. jdbc.password = 861221293

7. 编写日志配置log4j2.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- 日志文件 -->
  3. <Configuration status="WARN">
  4. <Appenders>
  5. <!--Console向控制台追加日志 SYSTEM_OUT系统输出控制台 -->
  6. <Console name="Console" target="SYSTEM_OUT">
  7. <PatternLayout pattern=" 日志log: %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n "/>
  8. </Console>
  9. </Appenders>
  10. <!-- 记录哪些类的日志信息 -->
  11. <Loggers>
  12. <!--DEBUG 是日志级别 调试信息也会记录 -->
  13. <Logger name="com.xgf.dao" level="DEBUG"/>
  14. <Root level="error">
  15. <AppenderRef ref="Console"/>
  16. </Root>
  17. </Loggers>
  18. </Configuration>

8. 配置Spring核心配置文件applicationContext.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mybatis="http://mybatis.org/schema/mybatis-spring" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
  3. <!--1. 引入jdbc的属性文件,在配置中通过占位使用 -->
  4. <context:property-placeholder location="classpath*:db.properties" />
  5. <!--2. <context:component-scan>扫描包中注解所标注的类(@Component、@Service、@Controller、@Repository) -->
  6. <context:component-scan base-package="com.xgf"/>
  7. <!--3. 由spring管理 配置数据源数据库连接(从jdbc属性文件中读取参数) -->
  8. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  9. <property name="username" value="${jdbc.username}"/>
  10. <property name="password" value="${jdbc.password}"/>
  11. <property name="url" value="${jdbc.url}"/>
  12. <property name="driverClassName" value="${jdbc.driver}"/>
  13. </bean>
  14. <!-- 通过spring来管理Mybatis的sqlSessionFactory对象创建,将MyBatis的二级缓存配置configLocation粘入 -->
  15. <!--4. 通过完全限定名匹配查找 创建SqlSessionFactoryBean -->
  16. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  17. <property name="dataSource" ref="dataSource" />
  18. </bean>
  19. <!-- 5. mybatis提供的一个注解扫描标签(搜索映射器 Mapper 接口),通过自动扫描注解的机制,创建每个dao接口定义的bean -->
  20. <mybatis:scan base-package="com.xgf.dao"/>
  21. </beans>

9. 创建获取class类的工具类GetDaoUtils

  1. // 获取bean工具类
  2. public class GetDaoUtils {
  3. private static ApplicationContext applicationContext = null;
  4. //静态代码块 只加载一次
  5. static {
  6. //加载配置文件
  7. applicationContext = new ClassPathXmlApplicationContext("com/xgf/config/applicationContext.xml");
  8. }
  9. public static <T> T getMapper(Class classFile) {
  10. return (T) applicationContext.getBean(classFile);
  11. }
  12. }

10. 运行测试类,测试逻辑是否有问题

测试结果,测试成功
>Preparing: select uid,username,password,name,birthday,sex,telephone,email,status,code from tab\_user where username = ? and password = ?

11. 编写随机生成验证码的业务逻辑类

  1. /* * 生成验证码,并将验证码转化为图片的业务层 * */
  2. public class VerificationCodeService {
  3. public VerificationCodeService() {
  4. }
  5. // 生成验证码字符串 -- 随机数
  6. public String createRandomCode() {
  7. String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";//所有随机数字符串集合
  8. //Random类 产生指定范围内的随机数
  9. Random random = new Random();
  10. StringBuilder sb = new StringBuilder();
  11. //随机截取4个字符
  12. for(int i =0 ;i < 4; i++){ //4个随机数
  13. //包括开头不包括结尾 从0到str.length()-1里面随机产生一个整数
  14. int index = random.nextInt(str.length());//从0到str.length()不包括最后一个 右边开区间
  15. char randomStr = str.charAt(index);//安装随机产生的值获取字符
  16. sb.append(randomStr);//StringBuilder拼接字符串
  17. }
  18. return sb.toString();
  19. }
  20. // 将生成的随机字符串验证码转化为图片
  21. public BufferedImage changeStringToImage(String code) {
  22. Random rd = new Random();
  23. //创建一个画布
  24. int width = 80;
  25. int height = 30;
  26. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  27. //创建画笔
  28. Graphics g = image.getGraphics();
  29. //给画笔设置颜色(绘制随机验证码的时候的验证码颜色)
  30. g.setColor(new Color(240,240,240)); //#00000 FFFFFF
  31. //设置验证码的 背景色
  32. g.fillRect(0, 0, width, height);
  33. // 设置字体
  34. g.setFont(new Font("宋体",Font.BOLD,16));
  35. g.setColor(new Color(0,0,0)); //#00000 FFFFFF
  36. // g.drawString(checkCodeStr, 20, 20);
  37. for (int i = 0; i <4 ; i++) {
  38. //画字符
  39. g.setColor(new Color(rd.nextInt(120),rd.nextInt(120),rd.nextInt(120)));
  40. g.drawString(code.charAt(i)+"", 16*i + rd.nextInt(16), 15 + rd.nextInt(10) );
  41. if(i % 2 == 0) { //画线
  42. g.setColor(new Color(rd.nextInt(120), rd.nextInt(120), rd.nextInt(120)));
  43. g.drawLine(rd.nextInt(75), rd.nextInt(28), rd.nextInt(75), rd.nextInt(28));
  44. }
  45. }
  46. return image;
  47. }
  48. }

12. 编写图片验证码的servlet

  1. // 验证码-生成验证码显示成图片的servlet
  2. @WebServlet("/checkCodeServlet")
  3. public class CheckCodeServlet extends HttpServlet {
  4. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  5. doGet(request,response);
  6. }
  7. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  8. //服务器通知浏览器不要缓存
  9. response.setHeader("pragma","no-cache");
  10. response.setHeader("cache-control","no-cache");
  11. response.setHeader("expires","0");
  12. //1:创建一个验证码的业务
  13. VerificationCodeService vcs = new VerificationCodeService();
  14. //2:生产一个随机的4个字符组成的字符串
  15. String verificationCode = vcs.createRandomCode();
  16. System.out.println(verificationCode);
  17. //将验证码保存到session中
  18. HttpSession session = request.getSession();
  19. session.setAttribute("verificationCode",verificationCode);
  20. // request.setAttribute("verificationCode",verificationCode);
  21. //3:将字符串转成图片
  22. //BufferedImage类将图片生成到内存中,然后直接发送给浏览器
  23. BufferedImage image = vcs.changeStringToImage(verificationCode);
  24. //4:使用OutputStream写到浏览器
  25. // System.out.println(image);
  26. //获取输出流
  27. ServletOutputStream outputStream = response.getOutputStream();
  28. ImageIO.write(image,"jpeg",outputStream);//参1,内存中的图片 参2,格式 参3,字节输出流
  29. outputStream.flush();
  30. outputStream.close();//关流
  31. // request.getRequestDispatcher("/").forward(request,response);
  32. }
  33. }

13. 登录servlet

  1. @WebServlet("/LoginServlet")
  2. public class LoginServlet extends HttpServlet {
  3. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  4. doGet(request, response);
  5. }
  6. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  7. UserService userService = new UserService();
  8. HttpSession session = request.getSession();//获取session对象,里面主要是验证码和当前user
  9. Msg msg = new Msg();//提示信息
  10. //用户输入的验证码
  11. String inputCheckCode = request.getParameter("inputCheckCode");
  12. //从session中获取系统当前生成的验证码
  13. String verificationCode = (String) session.getAttribute("verificationCode");
  14. System.out.println("inputCheckCode : " + inputCheckCode + " ;\t verificationCode : " + verificationCode);
  15. //inputCheckCode 与 verificationCode
  16. //相同表示验证码不正确,将提示信息写到页面的错误提示
  17. if (inputCheckCode == null || !inputCheckCode.equalsIgnoreCase(verificationCode)) {
  18. //验证码不看大小写
  19. msg.setCode(-3);
  20. msg.setData("验证码输入出错,请重新输入验证码");
  21. //将字符串转换为json数据格式返回给浏览器
  22. String json = new ObjectMapper().writeValueAsString(msg);
  23. response.getWriter().println(json);
  24. return; //返回不继续执行
  25. }
  26. //获取请求参数
  27. Map<String, String[]> map = request.getParameterMap();
  28. //当前登录用户
  29. User loginUser = new User();
  30. try {
  31. //参1 javaBean 参2 map 封装bean对象
  32. BeanUtils.populate(loginUser, map);//将map里面所有的参数赋值给javaBean(login就是输入的username和password)
  33. } catch (IllegalAccessException e) {
  34. e.printStackTrace();
  35. } catch (InvocationTargetException e) {
  36. e.printStackTrace();
  37. }
  38. //调用service处理参数,查询当前登录username和password是否存在
  39. int code = userService.login(loginUser);
  40. //响应给浏览器 ajax 是响应json给浏览器就可以
  41. msg.setCode(code);//设置code
  42. if (code == 1) {
  43. msg.setData("登录成功,欢迎您的使用Login Success");
  44. //将登录user保存到session中
  45. session.setAttribute("user", loginUser);
  46. //判断是否开启免登陆
  47. //登录成功且开启了十天免登陆 就要保存/覆盖cookie
  48. String ssh = request.getParameter("ssh");
  49. //从session中删除生成的验证码 不移除的话可能会覆盖新的验证码
  50. session.removeAttribute("verificationCode");
  51. } else if (code == -1) {
  52. msg.setData("您输入的用户名或密码错误,请重新输入Incorrect user name or password");
  53. } else if (code == -2) {
  54. msg.setData("您的账号还没有激活,请前往激活The account is activated");
  55. }
  56. //将字符串转成json数据格式,返回给浏览器显示提示信息msg
  57. String json = new ObjectMapper().writeValueAsString(msg);
  58. response.getWriter().println(json);
  59. }
  60. }

14. 编写filter,全局编码解决

  1. //解决全站乱码问题,处理所有的请求,拦截所有设置编码
  2. @WebFilter("/*")
  3. public class CharchaterFilter implements Filter {
  4. public void init(FilterConfig filterConfig) throws ServletException {
  5. }
  6. @Override
  7. public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
  8. System.out.println("CharchaterFilter");
  9. //设置请求编码
  10. req.setCharacterEncoding("UTF-8");
  11. //设置响应编码
  12. resp.setContentType("text/html;charset=UTF-8");
  13. //放行
  14. chain.doFilter(req, resp);
  15. }
  16. public void destroy() {
  17. }
  18. }

15. 编写页面jsp,点击验证码进行图片更换

  1. <section id="login_wrap">
  2. <div class="fullscreen-bg" style="background: url(images/login_bg.png);height: 532px;">
  3. </div>
  4. <div class="login-box">
  5. <div class="title">
  6. <img src="images/login_logo.png" alt="">
  7. <span>欢迎登录途牛旅游账户</span>
  8. </div>
  9. <div class="login_inner">
  10. <!--登录错误提示消息-->
  11. <div id="errorMsg" class="alert alert-danger" ></div>
  12. <form id="loginForm" action="" method="post" accept-charset="utf-8">
  13. <input type="hidden" name="action" value="login"/>
  14. <input id="username" name="username" type="text" placeholder="请输入账号">
  15. <input id="password" name="password" type="password" placeholder="请输入密码" autocomplete="off">
  16. <div class="verify">
  17. <input name="inputCheckCode" type="text" placeholder="请输入验证码" autocomplete="off">
  18. <span><img src="checkCodeServlet" alt="" onclick="changeCheckCode(this)"></span>
  19. <script type="text/javascript">
  20. //图片点击事件
  21. function changeCheckCode(img) {
  22. img.src="checkCodeServlet?"+new Date().getTime();//添加时间戳
  23. }
  24. </script>
  25. </div>
  26. <div class="submit_btn" >
  27. <button id="btn_login" type="button">登录</button>
  28. <div class="auto_login">
  29. <%-- ssh : 免密码登录 --%>
  30. <input type="checkbox" name="ssh" value="ssh" class="checkbox" style="margin-left: 10px">
  31. <span >十天免登陆</span>
  32. </div>
  33. </div>
  34. </form>
  35. <div class="reg" >没有账户?<a href="javascript:;">立即注册</a></div>
  36. </div>
  37. </div>
  38. </section>
  39. <!--引入尾部-->
  40. <div id="footer">
  41. </div>

16. aJax实现异步登录,并判断输入是否合法,防止非法注入

  1. <script type="text/javascript" >
  2. //检查用户名是否规范
  3. function checkUserName(){
  4. //获取输入框的值
  5. var username = $("#username").val();
  6. //正则表达式 定义一个规则,执行test方法,符合规则返回true,否则返回false
  7. var reg = /^\w{8,20}$/ ;
  8. var flag = reg.test(username); //判断
  9. //如果符合要求,设置输入框边框是正常,否则设置红色
  10. if(flag){
  11. $("#username").css("border","");
  12. }else{
  13. $("#username").css("border","1px solid red");
  14. }
  15. //alert(flag)
  16. return flag;
  17. }
  18. //检查密码是否规范
  19. function checkPassword(){
  20. //判断密码输入框的值是否合法
  21. var username = $("#password").val();
  22. var reg = /^\w{8,20}$/ ;
  23. var flag = reg.test(username); //判断
  24. if(flag){
  25. $("#password").css("border","");//无色框
  26. }else{
  27. $("#password").css("border","1px solid red");//红框
  28. }
  29. //alert(flag)
  30. return flag;
  31. }
  32. //页面加载执行函数
  33. $(function () {
  34. $("#errorMsg").html("");
  35. // 判断两个输入框架的是否格式正确
  36. $("#username").blur(checkUserName);//输入框失去焦点
  37. // 如果正确,使用ajax发送请求到servlet
  38. $("#password").blur(checkPassword);
  39. //登录判断,username、password是否符合注册规范,如果不符合报错(防止直接注入)
  40. $("#btn_login").click(function () {
  41. //alert("点击btn_login")
  42. //要求两个值正确,我们才做提交
  43. if(checkUserName()&&checkPassword()){
  44. var username = $("#username").val()
  45. var password = $("#password").val()
  46. var inputCheckCode = $("#inputCheckCode").val()
  47. //alert(username+password+inputCheckCode)
  48. //写提交
  49. $.ajax({
  50. url:"LoginServlet",
  51. async:true,
  52. data:$("#loginForm").serialize(),
  53. type:"post",
  54. dataType:"json",
  55. success:function (data) {
  56. // alert(data) {"code":1,"data":"登录成功"}
  57. if(1 == data.code){
  58. //跳转到主页 index.jsp
  59. $("#errorMsg").html("");
  60. window.location="index.jsp"
  61. }else{
  62. //显示在界面上
  63. $("#errorMsg").html(data.data);
  64. }
  65. },
  66. error:function () {
  67. alert("服务器发生了错误Error")//比如找不到servlet
  68. }
  69. });
  70. }else{
  71. $("#errorMsg").html("用户名或密码输入不规范,用户名密码错误");
  72. }
  73. })
  74. })
  75. </script>

17. 运行结果

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

发表评论

表情:
评论列表 (有 0 条评论,289人围观)

还没有评论,来说两句吧...

相关阅读