JavaWeb开发实战(一)

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDSClaw,2核4GB
RDS AI 助手,专业版
简介: JavaWeb开发实战(一)

一、业务需求

实现用户登录和退出登录功能,要求一个用户只在一处登录。完成对用户表的CRUD操作。

主要以消化技术为主。

二、技术栈

JSP、Servlet、Filter、Listener、JDBC、MySQL

三、创建数据库表

CREATE TABLE `users` (
 `userid` int(11) NOT NULL AUTO_INCREMENT,
 `username` varchar(30) DEFAULT NULL,
 `userpwd` varchar(30) DEFAULT NULL,
 `usersex` varchar(2) DEFAULT NULL,
 `phonenumber` varchar(30) DEFAULT NULL,
 `qqnumber` varchar(20) DEFAULT NULL,
 PRIMARY KEY (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

四、搭建环境

4.1 创建web项目

4.2 添加jar

用到数据库:MySQL驱动的jar

用到servlet:servlet-api.jar

页面中中使用jstl标签库:jstl标签库jar包

4.3 添加jstl标签库的约束文件

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

五、创建项目包以及工具类

5.1 创建项目包

5.2 创建POJO

package com.zj.pojo;
public class User {
    private int userid;
    private String username;
    private String userpwd;
    private String usersex;
    private String phonenumber;
    private String qqnumber;
    public User() {
    }
    public User(int userid, String username, String userpwd, String usersex, String phonenumber, String qqnumber) {
        this.userid = userid;
        this.username = username;
        this.userpwd = userpwd;
        this.usersex = usersex;
        this.phonenumber = phonenumber;
        this.qqnumber = qqnumber;
    }
    public int getUserid() {
        return userid;
    }
    public void setUserid(int 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 getUsersex() {
        return usersex;
    }
    public void setUsersex(String usersex) {
        this.usersex = usersex;
    }
    public String getPhonenumber() {
        return phonenumber;
    }
    public void setPhonenumber(String phonenumber) {
        this.phonenumber = phonenumber;
    }
    public String getQqnumber() {
        return qqnumber;
    }
    public void setQqnumber(String qqnumber) {
        this.qqnumber = qqnumber;
    }
    @Override
    public String toString() {
        return "User{" +
                "userid=" + userid +
                ", username='" + username + '\'' +
                ", userpwd='" + userpwd + '\'' +
                ", usersex='" + usersex + '\'' +
                ", phonenumber='" + phonenumber + '\'' +
                ", qqnumber='" + qqnumber + '\'' +
                '}';
    }
}

5.3 创建JDBC工具类

在src下创建db.properties属性文件

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
package com.zj.commons;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ResourceBundle;
public class jdbcUtils {
    private static String driver;
    private static String url;
    private static String username;
    private static String password;
    //初始化数据库驱动,读取db.properties配置文件的信息(static中的资源只会加载一次)
    static {
        ResourceBundle resourceBundle = ResourceBundle.getBundle("db");
        driver = resourceBundle.getString("jdbc.driver");
        url = resourceBundle.getString("jdbc.url");
        username = resourceBundle.getString("jdbc.username");
        password = resourceBundle.getString("jdbc.password");
        //加载数据库驱动
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //获取连接
    public static Connection getConnection(){
        Connection con = null;
        try {
        con = DriverManager.getConnection(url, username, password);
        }catch (Exception e){
          e.printStackTrace();
        }
        return con;
    }
    //关闭连接
    public static void closeConnection(Connection con){
        try {
            con.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //事务回滚
    public static void rollbackConnection(Connection con) {
        try {
            con.rollback();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

六、用户登录业务的实现

6.1 创建登录页面

将样式文件先复制到web目录下。

在web目录下创建login.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html;
charset=utf-8" />
    <title>欢迎登录后台管理系统</title>
    <link href="css/style.css" rel="stylesheet" type="text/css" />
    <script language="JavaScript" src="js/jquery.js"></script>
    <script src="js/cloud.js" type="text/javascript"></script>
    <script language="javascript">
        if (window.parent.length>0){
            window.parent.location = "login.jsp";
        }
        $(function(){
            $('.loginbox').css({'position':'absolute','left':($(window).width
                ()-692)/2});
            $(window).resize(function(){
                $('.loginbox').css({'position':'absolute','left':($(window).width
                    ()-692)/2});
            })
        });
        /*点击验证码图片生成验证码*/
        function change() {
           $("#code").attr("src","ValidateCodeServlet.do?"+Math.random())
        }
    </script>
</head>
<body style="background-color:#1c77ac;
background-image:url(images/light.png);
background-repeat:no-repeat; background-position:center top;
        overflow:hidden;">
<div id="mainBody">
    <div id="cloud1" class="cloud"></div>
    <div id="cloud2" class="cloud"></div>
</div>
<div class="logintop">
    <ul>
        <li><a href="#">回首页</a></li>
        <li><a href="#">帮助</a></li>
        <li><a href="#">关于</a></li>
    </ul>
</div>
<div class="loginbody">
    ${requestScope.msg}
    <div class="loginbox loginbox2">
        <form action="login.do" method="post">
            <ul>
                <li><input name="username" type="text" class="loginuser" value="admin" onclick="JavaScript:this.value=''"/></li>
                <li><input name="userpwd" type="password" class="loginpwd" value="" onclick="JavaScript:this.value=''"/></li>
                <li class="yzm">
                    <span><input name="code" type="text" value="验证码" onclick="JavaScript:this.value=''"/></span><cite><img id="code" src="ValidateCodeServlet.do" onclick="change()"/></cite>
                </li>
                <li><input name="" type="submit" class="loginbtn" value="登录" onclick="javascript:window.location='main.html'"/></li>
            </ul>
        </form>
    </div>
</div>
</body>
</html>

 

6.2 创建登录业务的持久层

在Dao包下创建UserLoginDao接口,在接口中创建抽象方法selectUserByUserNameAndPassword。

package com.zj.dao;
import com.zj.pojo.User;
public interface UserLoginDao {
    public User selectUserByUserNameAndPassword(String userName, String password);
}

创建UserLoginDao接口的实现类UserLoginDaoImpl实现接口。

package com.zj.dao.impl;
import com.zj.commons.jdbcUtils;
import com.zj.dao.UserLoginDao;
import com.zj.pojo.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class UserLoginDaoImpl implements UserLoginDao {
    /*用户登录实现*/
    @Override
    public User selectUserByUserNameAndPassword(String userName, String password) {
        User user = null;
        Connection conn = null;
        try {
            conn = jdbcUtils.getConnection();
            PreparedStatement ps = conn.prepareStatement("select * from users where username = ? and userpwd = ?");
            ps.setString(1, userName);
            ps.setString(2, password);
            ResultSet resultSet = ps.executeQuery();
            while (resultSet.next()) {
                user = new User();
                user.setUsername(resultSet.getString("username"));
                user.setUserpwd(resultSet.getString("userpwd"));
                user.setUsersex(resultSet.getString("usersex"));
                user.setPhonenumber(resultSet.getString("phonenumber"));
                user.setQqnumber(resultSet.getString("qqnumber"));
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return user;
    }
}

6.3 登录业务的业务层

在Service包下创建UserLoginService接口,在接口中创建抽象方法userLogin。

package com.zj.service;
import com.zj.pojo.User;
public interface UserLoginService {
    public User userLogin(String username, String password);
}

创建UserLoginService接口的实现类UserLoginServiceImpl实现接口。

package com.zj.service.Impl;
import com.zj.dao.UserLoginDao;
import com.zj.dao.impl.UserLoginDaoImpl;
import com.zj.exception.UserNotFoundException;
import com.zj.pojo.User;
import com.zj.service.UserLoginService;
/*用户登录业务*/
public class UserLoginServiceImpl implements UserLoginService {
    @Override
    public User userLogin(String username, String password) {
        //创建持久层对象
        UserLoginDao userLoginDao = new UserLoginDaoImpl();
        User user = userLoginDao.selectUserByUserNameAndPassword(username, password);
        if (user == null) {
           throw new UserNotFoundException("用户名或密码有误!");
        }
        return user;
    }
}

同时创建异常类UserNotFoundException,当没有查到用户的信息的时候抛出异常,要继承RuntimeException 。

package com.zj.exception;
/*用户登录状态的自定义异常*/
public class UserNotFoundException extends RuntimeException {
   public UserNotFoundException(){
    }
   public UserNotFoundException(String message) {
    }
   public UserNotFoundException(String message, Throwable cause) {
    }
}

6.4 创建登录业务的web层

在servlet包下创建UserLoginServlet 。

package com.zj.web.servlet;
import com.zj.commons.Constants;
import com.zj.exception.UserNotFoundException;
import com.zj.pojo.User;
import com.zj.service.Impl.UserLoginServiceImpl;
import com.zj.service.UserLoginService;
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("/login.do")
public class UserLoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        try {
            UserLoginService userLoginService = new UserLoginServiceImpl();
            User user = userLoginService.userLogin(username, password);
            //如果存在user,建立客户端和服务端的会话状态。
            HttpSession session = req.getSession();
            session.setAttribute(Constants.USER_SESSION_KEY,user);
            //使用重定向跳转到首页,因为可以改变地址栏的地址
            resp.sendRedirect("main.jsp");
        }catch (UserNotFoundException e) {//这是我们关心的异常
            //用户登陆失败跳转到登录页面
            req.setAttribute("msg",e.getMessage());
            req.getRequestDispatcher("login.jsp").forward(req,resp);
        }catch (Exception e) { //处理异常的最后一道防线,处理其他异常
            //出现其他错误
            resp.sendRedirect("error.jsp");
        }
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

在工具包创建Constants 抽象类(不能被实例化)存放常量。

package com.zj.commons;
/*常量抽象类,避免字符串硬编码。不允许被实例化*/
public abstract class Constants {
    public static String USER_SESSION_KEY = "user";
}

在web目录下创建main.jsp,作为登录成功跳转的页面。其中main.jsp是由index.jsp、left.jsp、footer.jsp构成。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html;
charset=utf-8" />
    <title>信息管理系统界面</title>
</head>
<frameset rows="*,31" cols="*" frameborder="no" border="0"
          framespacing="0">
    <frameset cols="187,*" frameborder="no" border="0"
              framespacing="0">
        <frame src="left.jsp" name="leftFrame" scrolling="No"
               noresize="noresize" id="leftFrame" title="leftFrame" />
        <frame src="index.jsp" name="rightFrame" id="rightFrame"
               title="rightFrame" />
    </frameset>
    <frame src="footer.jsp" name="bottomFrame" scrolling="No"
           noresize="noresize" id="bottomFrame" title="bottomFrame" />
</frameset>
<noframes><body>
</body></noframes>
</html>
</html>

相关实践学习
自建数据库迁移到云数据库
本场景将引导您将网站的自建数据库平滑迁移至云数据库RDS。通过使用RDS,您可以获得稳定、可靠和安全的企业级数据库服务,可以更加专注于发展核心业务,无需过多担心数据库的管理和维护。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
6月前
|
安全 前端开发 Java
《深入理解Spring》:现代Java开发的核心框架
Spring自2003年诞生以来,已成为Java企业级开发的基石,凭借IoC、AOP、声明式编程等核心特性,极大简化了开发复杂度。本系列将深入解析Spring框架核心原理及Spring Boot、Cloud、Security等生态组件,助力开发者构建高效、可扩展的应用体系。(238字)
|
6月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
6月前
|
安全 Java 开发者
告别NullPointerException:Java Optional实战指南
告别NullPointerException:Java Optional实战指南
329 119
|
7月前
|
JavaScript Java 大数据
基于JavaWeb的销售管理系统设计系统
本系统基于Java、MySQL、Spring Boot与Vue.js技术,构建高效、可扩展的销售管理平台,实现客户、订单、数据可视化等全流程自动化管理,提升企业运营效率与决策能力。
|
7月前
|
人工智能 Java API
Java AI智能体实战:使用LangChain4j构建能使用工具的AI助手
随着AI技术的发展,AI智能体(Agent)能够通过使用工具来执行复杂任务,从而大幅扩展其能力边界。本文介绍如何在Java中使用LangChain4j框架构建一个能够使用外部工具的AI智能体。我们将通过一个具体示例——一个能获取天气信息和执行数学计算的AI助手,详细讲解如何定义工具、创建智能体并处理执行流程。本文包含完整的代码示例和架构说明,帮助Java开发者快速上手AI智能体的开发。
2708 8
|
7月前
|
人工智能 Java API
Java与大模型集成实战:构建智能Java应用的新范式
随着大型语言模型(LLM)的API化,将其强大的自然语言处理能力集成到现有Java应用中已成为提升应用智能水平的关键路径。本文旨在为Java开发者提供一份实用的集成指南。我们将深入探讨如何使用Spring Boot 3框架,通过HTTP客户端与OpenAI GPT(或兼容API)进行高效、安全的交互。内容涵盖项目依赖配置、异步非阻塞的API调用、请求与响应的结构化处理、异常管理以及一些面向生产环境的最佳实践,并附带完整的代码示例,助您快速将AI能力融入Java生态。
1159 12
|
7月前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
561 100
|
7月前
|
存储 前端开发 Java
【JAVA】Java 项目实战之 Java Web 在线商城项目开发实战指南
本文介绍基于Java Web的在线商城技术方案与实现,涵盖三层架构设计、MySQL数据库建模及核心功能开发。通过Spring MVC + MyBatis + Thymeleaf实现商品展示、购物车等模块,提供完整代码示例,助力掌握Java Web项目实战技能。(238字)
827 0
|
7月前
|
消息中间件 人工智能 Java
抖音微信爆款小游戏大全:免费休闲/竞技/益智/PHP+Java全筏开源开发
本文基于2025年最新行业数据,深入解析抖音/微信爆款小游戏的开发逻辑,重点讲解PHP+Java双引擎架构实战,涵盖技术选型、架构设计、性能优化与开源生态,提供完整开源工具链,助力开发者从理论到落地打造高留存、高并发的小游戏产品。
|
6月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
305 1