JavaWeb开发实战(一)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 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>

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
21天前
|
设计模式 安全 Java
Java并发编程实战:使用synchronized关键字实现线程安全
【4月更文挑战第6天】Java中的`synchronized`关键字用于处理多线程并发,确保共享资源的线程安全。它可以修饰方法或代码块,实现互斥访问。当用于方法时,锁定对象实例或类对象;用于代码块时,锁定指定对象。过度使用可能导致性能问题,应注意避免锁持有时间过长、死锁,并考虑使用`java.util.concurrent`包中的高级工具。正确理解和使用`synchronized`是编写线程安全程序的关键。
|
4天前
|
安全 Java 调度
Java线程:深入理解与实战应用
Java线程:深入理解与实战应用
24 0
|
2天前
|
消息中间件 缓存 NoSQL
Java多线程实战-CompletableFuture异步编程优化查询接口响应速度
Java多线程实战-CompletableFuture异步编程优化查询接口响应速度
|
3天前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
|
8天前
|
IDE Java 数据库连接
使用 Java 进行桌面应用开发
【4月更文挑战第19天】Java 是一款广泛应用于企业级、网络和桌面应用开发的编程语言。其跨平台特性使Java程序能在不同操作系统上运行,而JDK提供了开发所需工具和库。使用Swing等GUI库构建用户界面,结合JDBC进行数据库操作,Socket实现网络通信。虽然面临性能和用户体验的挑战,但通过优化和选用合适的IDE,Java仍能开发出高效稳定的桌面应用。
|
8天前
|
存储 Java 数据库连接
java DDD 领域驱动设计思想的概念与实战
【4月更文挑战第19天】在Java开发中,领域驱动设计(Domain-Driven Design, DDD) 是一种软件设计方法论,强调以领域模型为中心的软件开发。这种方法通过丰富的领域模型来捕捉业务领域的复杂性,并通过软件满足核心业务需求。领域驱动设计不仅是一种技术策略,而且还是一种与业务专家紧密合作的思维方式
31 2
|
9天前
|
前端开发 Java Go
开发语言详解(python、java、Go(Golong)。。。。)
开发语言详解(python、java、Go(Golong)。。。。)
|
9天前
|
人工智能 前端开发 Java
Java语言开发的AI智慧导诊系统源码springboot+redis 3D互联网智导诊系统源码
智慧导诊解决盲目就诊问题,减轻分诊工作压力。降低挂错号比例,优化就诊流程,有效提高线上线下医疗机构接诊效率。可通过人体画像选择症状部位,了解对应病症信息和推荐就医科室。
151 10
|
9天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
16天前
|
运维 NoSQL 算法
Java开发-深入理解Redis Cluster的工作原理
综上所述,Redis Cluster通过数据分片、节点发现、主从复制、数据迁移、故障检测和客户端路由等机制,实现了一个分布式的、高可用的Redis解决方案。它允许数据分布在多个节点上,提供了自动故障转移和读写分离的功能,适用于需要大规模、高性能、高可用性的应用场景。
16 0