【JSP+Servlet】实现登录和注册

  • JSP+SerVlet,对Servlet和Dao层进行优化,抽取出共同代码

  • 只实现了简单的登录和注册,用户名查重、记住用户名和密码、验证码、表单校验并没有实现

  • 👉 GitHub源码地址



前端界面

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

代码结构

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

1. 建立登录注册相关模型(Bean层)

  • 建立用户表user

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
  • 建立对应的User类

/**
 * 对应数据库中的user表
 */
public class User {

    private Integer id;
    private String username;
    private String password;

    public User(Integer id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;

    }
    // 无参构造函数必须得有
    public User() {
        super();
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }



    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}


2. 建立Utils层获取数据库连接

使用 JDBC + c3p0 获取数据库连接

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、Spring等。

导包并右键 add as library
在这里插入图片描述
JDBCUtils

/**
 * 获取数据库连接的工具类
 *
 * @author smallbeef
 *
 */
public class JDBCUtils {
	// 此处要与c3p0的配置文件中的name一致
    private static ComboPooledDataSource dataSource = new ComboPooledDataSource(
            "c3p0Config");

    private JDBCUtils() {
    }

    /**
     * 获取数据库连接
     *
     * @return 如果获取连接成功,返回数据的连接对象。<br/>
     *         如果获取数据库连接失败,则返回null
     */
    public static Connection getConnection() {
        Connection connection = null;
        try {
            // 从c3p0中获取数据库连接
            connection = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 释放数据库连接
     */
    public static void closeConnection(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        getConnection();
    }
}

c3p0-config.xml

<c3p0-config>
	<!-- 用户自定义配置 -->
	<named-config name="c3p0Config">
			<property name="driverClass">com.mysql.jdbc.Driver</property>
			<property name="jdbcUrl">jdbc:mysql://localhost:3306/userandbook</property>
			<property name="user">root</property>
			<property name="password">root</property>
			<!-- 最大连接数 -->
			<property name="maxPoolSize">10</property>
			<!-- 最小连接数 -->
			<property name="minPoolSize">5</property>
			<!-- 初始化连接数,连接池创建初始化连接数 -->
			<property name="initialPoolSize">3</property>
			<!-- 多长时间检测一下链接的可用性,以秒做单位-->
			<property name="idleConnectionTestPeriod">3600</property>
			<!-- 如果连接处不够用,一次性创建多少链接 -->
			<property name="acquireIncrement">5</property>
			<!-- 链接的最大空闲时间,以分钟做为单位 -->
			<property name="maxIdleTime">50</property>
	</named-config>	

</c3p0-config>

应当把c3p0-config.xml 放在 src 下,不然 new ComboPooledDataSource(“configName"); 可能会找不到 c3p0-config.xml 文件

数据库连接测试

public class JDBCUtilTest {

	@Test
	public void testGetConnection() {
		Connection conn = JDBCUtils.getConnection();
		System.out.println(conn);
		JDBCUtils.closeConnection(conn);
	}
	
}

在这里插入图片描述
连接成功!


3. 建立Dao层操作数据库数据

  • 建立BaseDao, 专门被其他Dao继承,BaseDao定义一些基础方法(泛型)

    导包:DButils
    使用 DBUtils的QueryRunner.update / query 方法实现增删改查

    DbUtils是一种 JDBC Utility Component (翻译过来大概就是:JDBC实用部件),故名思意,和数据库操作有关。官网上的简介也称之为 JDBC helper library ,由此可知,DbUtils是一个工具类库,用来进行数据库通信的
    👉 【JavaWeb】DbUtils入门之QueryRunner

    BaseDao

public class BaseDao<T> {
    // 需要获取实际的type
    private Class<T> type;

    private QueryRunner queryRunner = new QueryRunner();

    public BaseDao(){
        // 获取父类的类型,父类是带参数的
        ParameterizedType superclass = (ParameterizedType) this.getClass().getGenericSuperclass();
        System.out.println(superclass.getClass());
        // 获取泛型中的具体的类型的class
        type = (Class<T>) superclass.getActualTypeArguments()[0];
    }

    /**
     * 获取一个对象
     * @param sql  sql语句
     * @param params 可变参数
     * @return
     */
    public T getBean(String sql, Object...params){
        Connection connection = JDBCUtils.getConnection();
        T query = null;
        try {
            // 查询一个数据,BeanHandler封装一个对象
            query = queryRunner.query(connection,sql,new BeanHandler<>(type),params);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeConnection(connection);
        }
        return query;
    }

    /**
     * 获取对象的集合
     * @return
     */
    public List<T> getBeanList(String sql, Object...params){
        Connection connection = JDBCUtils.getConnection();
        List<T> query = null;
        try {
            // 查询一组数据,BeanListHandler封装一组对象
            query = queryRunner.query(connection,sql,new BeanListHandler<>(type),params);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeConnection(connection);
        }

        return query;
    }

    
    /**
     * 执行增删改
     */
    public int update(String sql, Object ...params){
        int count = 0;
        Connection connection = JDBCUtils.getConnection();
        try {
            count = queryRunner.update(connection, sql, params);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeConnection(connection);
        }
        return count;
    }


}

  • UserDao: 继承BaseDao操作User表

    面向接口编程 : 定义UserDao接口UserDaoImpl 实现
/**
 * UserDAO具体的实现类
 *
 * @author smallbeef
 *
 */
public class UserDaoImp extends BaseDao<User> implements UserDao {

    /**
     * 按照用户名和密码查询信息
     * @param user
     * @return
     */
    @Override
    public User getUserByUserNameAndPassWord(User user) {
        String sql = "select id,username,password from user where username = ? and password = ?";
        User bean = this.getBean(sql, user.getUsername(), user.getPassword());
        return bean;
    }

    /**
     * 注册 保存用户
     * @param user
     * @return
     */
    @Override
    public boolean registUser(User user) {
        String sql = "insert into user(`id`,`username`,`password`) values(null, ?, ?)";
        int update = this.update(sql, user.getUsername(), user.getPassword());
        if(update>0){
            return true;
        }else
            return false;
    }
}

4. 建立service层

  • UserService 完成用户的登录注册功能

public class UserServiceImp implements UserService {
    private UserDao ud = new UserDaoImp();

    @Override
    public User login(User user) {
        return ud.getUserByUserNameAndPassWord(user);
    }

    @Override
    public boolean regist(User user) {
        return ud.registUser(user);
    }
}

5. 建立servlet层:处理用户请求

一般是建立 LoginServletRegistServlet , 注册和登录界面表单分别调用不同的servlet。

此处我们希望一个UserServlet就能够处理注册和登录请求,让用户的注册和登录请求都经过同一个Userservlet,而不是分别经过loginservlet和registservlet。

实现方法:给form表单带上method参数请求UserServlet,UserServlet通过这个参数判断是注册请求还是登录请求

<form action="/UserServlet?method=login" method="post">

<form action="/UserServlet?method=regist" method="post">

在这里插入图片描述
UserServelt

@WebServlet(name = "UserServlet", urlPatterns = "/UserServlet")
public class UserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String method = request.getParameter("method");
        System.out.println(method);
        if("regist".equals(method)){
            //注册
            regist(request,response);
        }
        if("login".equals(method)){
            //登录
            login(request,response);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }

    private UserService us = new UserServiceImp();

    protected void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        boolean b = us.regist(new User(null, username, password));
        if(b){
            //注册成功,返回成功页面,重定向
            request.getRequestDispatcher("/pages/regist_success.html").forward(request,response);

        }else{
            //注册失败,返回失败页面,转发
            response.sendRedirect(request.getContextPath()+"/pages/error.jsp");
        }
    }

    protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = us.login(new User(null, username, password));
        if(user == null){
            //登录失败,返回登录页面,转发(换界面)
            request.getRequestDispatcher("/pages/error.jsp").forward(request,response);
        }else{
            //登录成功,返回成功界面 重定向(直接刷新界面)
            response.sendRedirect(request.getContextPath() + "/pages/login_success.html");
        }
    }
}

为了不陷入层层的if判断,我们利用反射来优化此代码

反射:你指定一个方法名,我找到这个方法并直接调用)

public class UserServlet extends HttpServlet {   
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取要调用的方法
        String method = request.getParameter("method");
        System.out.println(method);
        // getDeclaredMethod(方法名,参数列表(传的是各个参数的类))

        // 通过反射找到该方法并调用
        try {
            Method declaredMethod = this.getClass().getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class);
            // 把方法权限设大
            declaredMethod.setAccessible(true);
            // invoke(对象,参数) 执行该方法
            declaredMethod.invoke(this,request,response);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
//        if("regist".equals(method)){
//            //注册
//            regist(request,response);
//        }
//        if("login".equals(method)){
//            //登录
//            login(request,response);
//        }
    }

所有的servlet都是通过反射来调用相应的方法,所以我们可以抽取出一个BaseServlet

抽取之后Userservlet只需要编写相关逻辑代码就可以了,以后定义的任何方法只需要在form表单上带上方法名即可

在这里插入图片描述

BaseServlet

public class BaseServlet extends HttpServlet {
//    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

//    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 解决post乱码问题,设置请求的参数字符集为UTf-8
        request.setCharacterEncoding("UTF-8");
        // 获取要调用的方法
        String method = request.getParameter("method");
        System.out.println(method);

        // 通过反射找到该方法并调用
        // getDeclaredMethod(方法名,参数列表(传的是各个参数的类))
        try {
            Method declaredMethod = this.getClass().getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class);
            // 把方法权限设大
            declaredMethod.setAccessible(true);
            // invoke(对象,参数) 执行该方法
            declaredMethod.invoke(this,request,response);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }
}

UserServlet

@WebServlet(name = "UserServlet" ,urlPatterns = "/UserServlet")
public class UserServlet extends BaseServlet {


    private UserService us = new UserServiceImp();

    protected void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        boolean b = us.regist(new User(null, username, password));
        if(b){
            //注册成功,返回成功页面,重定向
            request.getRequestDispatcher("/pages/regist_success.html").forward(request,response);

        }else{
            //注册失败,返回注册页面,转发
            response.sendRedirect(request.getContextPath()+"/pages/error.html");
        }
    }

    protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = us.login(new User(null, username, password));
        if(user == null){
            //登录失败,返回登录页面,转发(换界面)
            request.getRequestDispatcher("/pages/error.html").forward(request,response);
        }else{
            //登录成功,返回成功界面 重定向(直接刷新界面)
            response.sendRedirect(request.getContextPath() + "/pages/login_success.html");
        }
    }
}

一连串的request.getParameter取参过程其实也可以抽取出来,此处就不做了


注意修改域名为默认:
在这里插入图片描述

  • 24
    点赞
  • 199
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
实现注册登录功能需要以下几个步骤: 1. 创建数据库表:首先需要创建一个用户表,用于存储用户的注册信息。 2. 编写JavaBean类:创建一个User类,包含用户的注册信息,如用户名、密码、邮箱等。 3. 实现注册功能:在JSP页面中,收集用户的注册信息,将信息传递给后台ServletServlet将信息存入数据库中。 4. 实现登录功能:在JSP页面中,收集用户的登录信息,将信息传递给后台ServletServlet查询数据库中是否存在匹配的用户信息,如果有,则跳转到登录成功页面,否则提示用户名或密码错误。 下面是一个简单的示例代码: 1. 创建用户表 CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(50) NOT NULL, `email` varchar(50) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 2. 编写JavaBean类 public class User { private int id; private String username; private String password; private String email; //省略getter和setter方法 } 3. 实现注册功能 //register.jsp <form action="register" method="post"> <input type="text" name="username" placeholder="用户名"><br> <input type="password" name="password" placeholder="密码"><br> <input type="text" name="email" placeholder="邮箱"><br> <input type="submit" value="注册"> </form> //RegisterServlet.java @WebServlet("/register") public class RegisterServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取用户注册信息 String username = request.getParameter("username"); String password = request.getParameter("password"); String email = request.getParameter("email"); //创建User对象,将用户信息存入数据库 User user = new User(); user.setUsername(username); user.setPassword(password); user.setEmail(email); UserDao userDao = new UserDao(); userDao.addUser(user); //跳转到注册成功页面 response.sendRedirect("registersuccess.jsp"); } } 4. 实现登录功能 //login.jsp <form action="login" method="post"> <input type="text" name="username" placeholder="用户名"><br> <input type="password" name="password" placeholder="密码"><br> <input type="submit" value="登录"> </form> //LoginServlet.java @WebServlet("/login") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取用户登录信息 String username = request.getParameter("username"); String password = request.getParameter("password"); UserDao userDao = new UserDao(); User user = userDao.getUserByUsername(username); //判断用户名和密码是否匹配 if(user != null && user.getPassword().equals(password)) { //登录成功,将用户信息存入Session中 HttpSession session = request.getSession(); session.setAttribute("user", user); //跳转到登录成功页面 response.sendRedirect("loginsuccess.jsp"); } else { //登录失败,返回登录页面并提示错误信息 request.setAttribute("error", "用户名或密码错误"); request.getRequestDispatcher("login.jsp").forward(request, response); } } } 以上代码只是一个简单的实现,实际开发中还需要进行数据校验、防止SQL注入等安全措施。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞天小牛肉

您的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值