大纲:

1.数据库表设计 tb_user  (mysql)
2.前端页面设计
    登录页面 login.jsp
        登录校验 js校验
        登录表单校验
    *1.给登录按钮绑定点击事件
    *2.获取用户姓名,判断姓名是否为空,如果为空,则提示(span标签赋值),并且return
    *3.获取密码,判断密码是否为空,如果为空,则提示(span标签赋值)并且return
    *4.都不为空,则手动提交表单

    首页 index.jsp
3.后台代码
   登录功能
 controller层
    请求接收(调用service层,返回结果)
    响应结果
*  1.接收客户端的请求(接收参数:姓名,密码)
*  2.调用service层的方法,返回消息模型对象
*  3.判断消息模型状态码
*     失败,将消息模型对象设置到request作用域中,请求转发到登录页面 login.jsp
*     成功,将用户信息设置到session作用域中,重定向到首页 index.jsp

 service层
    业务逻辑判断
* 1.参数非空判断
*      参数为空,将状态码,设置提示信息,回显数据 设置到消息模型中,返回消息模型对象
* 2.参数不为空,调用mapper(dao)层的查询方法,通过用户名查询用户对象
* 3.判断用户对象是否为空
*      为空,将状态码,设置信息提示,回显数据 设置到消息模型中,返回消息模型对象
* 4.不为空,判断前台输入的密码是否与数据库查询出来的密码一致
*      不一致, 将状态码,设置信息提示,回显数据 设置到消息模型中,返回消息模型对象
* 5.一致,将成功状态,提示信息,用户对象设置为消息模型对象,并return
 dao层 mapper
    接口类
    mapper.xml mybatis与数据库的相关操作
 entity(po,model)
    JavaBean实体
 util
    工具类(通用的方法/类)
 test
    测试类/方法

        1.数据库表设计(tb_user)

DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
`userId`  int NOT NULL AUTO_INCREMENT ,
`userName`  varchar(20) NOT NULL ,
`userPwd`  varchar(30) NOT NULL ,
`userAge`  int NULL DEFAULT 18 ,
PRIMARY KEY (`userId`)
);
-- 插入两条记录
INSERT INTO `tb_user` VALUES ('1', 'kql', '123123', '18'), ('2', 'wgy', '456789', '18');

   2.登录页面 (login.jsp)

<%--
  Created by IntelliJ IDEA.
  User: Lenovo
  Date: 2022/12/10
  Time: 12:58
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户登录</title>
</head>
<body>
<div style="text-align: center">
    <form action="login" method="post" id="loginForm">
    姓名:<input type="text" name="uname" id="uname" value="${messageModel.object.userName}"/><br>
    密码:<input type="password" name="upwd" id="upwd" value="${messageModel.object.userPwd}"/><br>
        <span id="msg" style="font-size: 12px;color: darksalmon" >${messageModel.msg}</span><br>
        <button type="button" id="ubutton">登录</button>
        <button type="button">注册</button>
    </form>
</div>
<%-- 引入jquery的js文件--%>
<script type="text/javascript" src="js/jquery.txt"></script>

<script type="text/javascript">
    $("#ubutton").click(function (){
        var uname = $("#uname").val();
        var upwd = $("#upwd").val();
        if (isEmpty(uname)){
            $("#msg").html("用户姓名不能为空!")
            return;
        }
        if(isEmpty(upwd)){
            $("#msg").html("用户密码不能为空!")
            return;
        }
        $("#loginForm").submit();

    }) ;

    /**
     * 判断字符串书否为空
     * 为空返回true
     * 不为空返回false
     * @param str
     * @returns {boolean}
     */
    function isEmpty(str){
        if(str == null || str.trim() == ""){
            return true;
        }
    return false;
    }
</script>

</body>
</html>

      3.首页 (index.jsp)

<%--
  Created by IntelliJ IDEA.
  User: Lenovo
  Date: 2022/12/9
  Time: 15:33
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>首页</title>
  </head>
  <body>
  <h2>欢迎${user.userName}登录</h2>
  </body>
</html>

        4.mysql.properties  (注意:这里password要改为自己的数据库密码,123456是小编的密码)

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/loginprogect
user=root
password=123456

       5.mybatis-config.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--
    properties 标签中的配置可以供整个配置文件使用,在任何位置都可以引入配置中的值
    properties 标签可以通过子标签 property 标签来配置一些元素信息,也可以配置外部的动态文件
    -->
    <properties resource="mysql.properties"/><!-- 也可以配置url,但url和resource只能存在一个-->
    <!-- 类型别名-->
   <!-- <typeAliases>
        <typeAlias type="com.kkk.entity.User" alias="User"/>
    </typeAliases>-->
    <!-- 对事物的管理和连接池的配置-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${user}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <!-- mapper映射器-->
    <mappers>
        <!-- 映射文件方式1,一个一个配置-->
      <!--  <mapper resource="com/kkk/mapper/UserMapper.xml"/>
        <mapper class="com.kkk.mapper.UserMapper"/>  -->

        <!-- 映射文件方式2,自动扫描包内的mapper接口和配置文件-->
        <package name="com.kkk.mapper"/>

    </mappers>

</configuration>

     6.GetSqlSession

package com.kkk.util;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;



import java.io.IOException;
import java.io.InputStream;

/**
 * @Author Lenovo
 * @ClassName GetSqlSession
 * @DATE 2022/12/10 22:05
 * @Description: 类的功能描述
 */
public class GetSqlSession {
    public static SqlSession createSqlSession() {
        SqlSessionFactory sqlSessionFactory = null;
        InputStream input = null;
        SqlSession session = null;

        try {
            //获取mybatis的配置文件
            String resource = "mybatis-config.xml";
            //以流的方式获取resource(mybatis的环境配置文件)
            input = Resources.getResourceAsStream(resource);
            //创建会话工厂
            sqlSessionFactory=new SqlSessionFactoryBuilder().build(input);
            //通过工厂得到sqlsession
            session=sqlSessionFactory.openSession();
            return session;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
    public static void main(String[] args){
        System.out.println(createSqlSession());
    }
}

      7.StringUtil

package com.kkk.util;

/**
 * @Author Lenovo
 * @ClassName StringUtil
 * @DATE 2022/12/11 15:48
 * @Description: 类的功能描述
 * 判断字符串是否为空  空 true
 *                  非空 false
 */
public class StringUtil {
    public static boolean isEmpty(String str){
        if(str == null || str.trim().equals("")){
            return true;
        }
        return false;
    }
}

   8.test

package com.kkk.test;

import com.kkk.entity.User;
import com.kkk.mapper.UserMapper;
import com.kkk.util.GetSqlSession;
import org.apache.ibatis.session.SqlSession;

/**
 * @Author Lenovo
 * @ClassName Test
 * @DATE 2022/12/11 10:16
 * @Description: 类的功能描述
 */
public class Test {
    public static void main(String[] args) {
        //获取sqlsession对象
        SqlSession session = GetSqlSession.createSqlSession();
        //得到对应的mapper
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //调用方法,返回用户对象
        User user = userMapper.selectByUserName("kql");
        System.out.println(user);
    }
}

     9.User

package com.kkk.entity;

/**
 * @Author Lenovo
 * @ClassName User
 * @DATE 2022/12/10 20:34
 * @Description: 用户实体类
 */
public class User {
    private Integer userId;
    private String userName;
    private String userPwd;
    private String userAge;

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPwd() {
        return userPwd;
    }

    public void setUserPwd(String userPwd) {
        this.userPwd = userPwd;
    }

    public String getUserAge() {
        return userAge;
    }

    public void setUserAge(String userAge) {
        this.userAge = userAge;
    }
}

           10.MessageModel

package com.kkk.entity.vo;

/**
 * @Author Lenovo
 * @ClassName MessageModel
 * @DATE 2022/12/11 15:55
 * @Description: 类的功能描述
 * 消息模型对象(数据响应)
 * 状态码
 *      1=成功   0=失败
 * 信息提示
 *      字符串
 * 回显数据
 *      object(基本数据类型,字符串,list,map)
 */
public class MessageModel {
    private Integer code;
    private String msg;
    private Object object;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }
}

          11.UserServlet

package com.kkk.controller;


import com.kkk.entity.User;
import com.kkk.entity.vo.MessageModel;
import com.kkk.service.UserService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Author Lenovo
 * @ClassName UserServlet
 * @DATE 2022/12/11 16:03
 * @Description: 类的功能描述
 *
 */

/**
 * controller层  (接受请求,响应结果)
 * 1.接收客户端的请求(接收参数:姓名,密码)
 * 2.调用service层的方法,返回消息模型对象
 * 3.判断消息模型状态码
 *      失败,将消息模型对象设置到request作用域中,请求转发到登录页面 login.jsp
 *      成功,将用户信息设置到session作用域中,重定向到首页 index.jsp
 *
 */
@WebServlet("/login")
public class UserServlet extends HttpServlet {
    //创建UserService对象
    private UserService userService=new UserService();
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       // 1.接收客户端的请求(接收参数:姓名,密码)
        String uname=request.getParameter("uname");
        String pwd=request.getParameter("upwd");
        //2.调用service层的方法,返回消息模型对象
        MessageModel messageModel=userService.userLogin(uname,pwd);
        //3.判断消息模型状态码

        if(messageModel.getCode() == 0){
            //失败,将消息模型对象设置到request作用域中,请求转发到登录页面 login.jsp
            request.setAttribute("messageModel",messageModel);
            request.getRequestDispatcher("login.jsp").forward(request,response);

        }else{
            //成功,将用户信息设置到session作用域中,重定向到首页 index.jsp
            request.getSession().setAttribute("user",messageModel.getObject());
            response.sendRedirect("index.jsp");
        }


    }
}

          12.UserServices

package com.kkk.service;

import com.kkk.entity.User;
import com.kkk.entity.vo.MessageModel;
import com.kkk.mapper.UserMapper;
import com.kkk.util.GetSqlSession;
import com.kkk.util.StringUtil;
import org.apache.ibatis.session.SqlSession;

/**
 * @Author Lenovo
 * @ClassName UserService
 * @DATE 2022/12/11 15:53
 * @Description: 类的功能描述
 * 业务逻辑
 * 1.参数非空判断
 *      参数为空,将状态码,设置提示信息,回显数据 设置到消息模型中,返回消息模型对象
 * 2.参数不为空,调用mapper(dao)层的查询方法,通过用户名查询用户对象
 * 3.判断用户对象是否为空
 *      为空,将状态码,设置信息提示,回显数据 设置到消息模型中,返回消息模型对象
 * 4.不为空,判断前台输入的密码是否与数据库查询出来的密码一致
 *      不一致, 将状态码,设置信息提示,回显数据 设置到消息模型中,返回消息模型对象
 * 5.一致,将成功状态,提示信息,用户对象设置为消息模型对象,并return
 */
public class UserService {
    public  MessageModel userLogin(String uname,String pwd){
        MessageModel messageModel=new MessageModel();
        //回显数据
        User u=new User();
        u.setUserName(uname);
        u.setUserPwd(pwd);
        messageModel.setObject(u);
        //1.参数非空判断
        if(StringUtil.isEmpty("uname")||StringUtil.isEmpty("pwd")){
            // 参数为空,将状态码,设置提示信息,回显数据 设置到消息模型中,返回消息模型对象
            messageModel.setCode(0);
            messageModel.setMsg("用户名和密码不能为空!!!!");

            return messageModel;
        }
        //2.参数不为空,调用mapper(dao)层的查询方法,通过用户名查询用户对象
        SqlSession session= GetSqlSession.createSqlSession();
        UserMapper userMapper=session.getMapper(UserMapper.class);
        User user=userMapper.selectByUserName(uname);

        //3.判断用户对象是否为空
        if(user == null) {
            //为空,将状态码,设置信息提示,回显数据 设置到消息模型中,返回消息模型对象
            messageModel.setCode(0);
            messageModel.setMsg("姓名不正确!!!");


            return messageModel;
        }
        //4.不为空,判断前台输入的密码是否与数据库查询出来的密码一致
        if(!user.getUserPwd().equals(pwd)){
            //不一致, 将状态码,设置信息提示,回显数据 设置到消息模型中,返回消息模型对象
            messageModel.setCode(0);
            messageModel.setMsg("密码错误!!!");

            return messageModel;
        }
        //5.一致,将成功状态,提示信息,用户对象设置为消息模型对象,并return
        messageModel.setCode(1);
        messageModel.setMsg("成功!");
        messageModel.setObject(user);
        return messageModel;
    }
}

         13.UserMapper

package com.kkk.mapper;

import com.kkk.entity.User;

/**
 * @Author Lenovo
 * @ClassName UserMapper
 * @DATE 2022/12/10 20:55
 * @Description: 类的功能描述
 */
public interface UserMapper {
    User selectByUserName(String userName);

}

       14.UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!-- @author:keqingling -->

<!-- 是否为Dao接口起别名 -->
<mapper namespace="com.kkk.mapper.UserMapper">
    <select id="selectByUserName" parameterType="String" resultType="com.kkk.entity.User">
        SELECT * FROM `tb_user` where userName=#{userName}

    </select>
</mapper>

            项目整个源码   

链接:https://pan.baidu.com/s/1hwkbvoDD_3vlzVqIVBcehw     

提取码:1234           

项目视频讲解:https://www.bilibili.com/video/BV1f54y1W7E6       (up主讲解的超详细)