JavaWebDemo

1.数据库准备

  • user表结构
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `sex` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
  • user表数据
INSERT INTO `user` (`id`, `username`, `password`, `sex`, `age`, `address`) VALUES (1, '张三丰', '111', '男', 150, '湖南');
INSERT INTO `user` (`id`, `username`, `password`, `sex`, `age`, `address`) VALUES (2, '玛卡巴卡', '111', '未知', 30, '花园宝宝');
  • 数据预览

在这里插入图片描述

2.三层架构

我们的开发架构一般都是基于两种形式,一种是 C/S 架构,也就是客户端/服务器,另一种是 B/S 架构,也就是浏览器服务器。在 JavaEE 开发中,几乎全都是基于 B/S 架构的开发。

那么在 B/S 架构中,系统标准的三层架构包括:表现层业务层持久层
三层架构

三层架构中,每一层各司其职,接下来我们就说说每层都负责哪些方面:

  • 表现层(web/servlet)

也就是我们常说的web层。它负责接收客户端请求,向客户端响应结果,通常客户端使用http协议请求web 层,web 需要接收 http 请求,完成 http 响应。

表现层包括展示层控制层:控制层负责接收请求,展示层负责结果的展示。

表现层依赖业务层,接收到客户端请求一般会调用业务层进行业务处理,并将处理结果响应给客户端。

表现层的设计一般都使用 MVC 模型。(MVC 是表现层的设计模型,和其他层没有关系)

MVC 全名是 Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,
是一种用于设计创建 Web 应用程序表现层的模式。MVC 中每个部分各司其职:

  • Model(模型):

通常指的就是我们的数据模型。作用一般情况下用于封装数据。

  • View(视图):

通常指的就是我们的 jsp 或者 html。作用一般就是展示数据的。
通常视图是依据模型数据创建的。

  • Controller(控制器):

是应用程序中处理用户交互的部分。作用一般就是处理程序逻辑的。

  • 业务层(service)

也就是我们常说的 service 层。它负责业务逻辑处理,和我们开发项目的需求息息相关。web 层依赖业务层,但是业务层不依赖 web 层。

业务层在业务处理时可能会依赖持久层,如果要对数据持久化需要保证事务一致性。(也就是我们说的,事务应该放到业务层来控制)

  • 持久层(dao)

也就是我们是常说的 dao 层。负责数据持久化,包括数据层即数据库和数据访问层,数据库是对数据进行持久化的载体,数据访问层是业务层和持久层交互的接口,业务层需要通过数据访问层将数据持久化到数据库中。通俗地讲,持久层就是和数据库交互,对数据库表进行增删改查的

3.项目搭建

3.1 项目结构

项目结构

3.2 导入依赖

  • pom.xml
	<dependencies>
		<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
		    <groupId>org.projectlombok</groupId>
		    <artifactId>lombok</artifactId>
		    <version>1.18.32</version>
		</dependency>
    </dependencies>

在这里插入图片描述

3.3 准备包结构

包结构

  • servlet 控制层代码,主要由负责接收请求和结果的展示。
  • service 服务层代码,主要用于处理业务逻辑
  • dao 数据访问层,主要用户定义对于各个表格的CURD的方法
  • pojo 实体类层,主要用于存放和数据库对应的实体类以及一些VO对象
  • util 工具类包,主要用存放一些工具类
  • filters 过滤器包,专门用于存放一些过滤器

3.4 准备工具类

3.4.1 JDBC工具类

  • Config 获取连接对象
package com.by.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class Config {
    private static String username;
    private static String password;
    private static String url;
    private static String driverClass;

    static{
        //特殊Hashtable
        Properties prop = new Properties();
        try {
            //读取类路径下的配置文件
            InputStream is = Config.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //InputStream in = new FileInputStream("javaweb\\user_mgr\\src\\main\\resources\\jdbc.properties");
            //加载配置文件内容
            prop.load(is);
            // acquire the properties from file
            username = prop.getProperty("username");
            password = prop.getProperty("password");
            url = prop.getProperty("url");
            driverClass = prop.getProperty("driverClass");
            // register the driver
            if(driverClass != null && url != null && username != null && password != null){
                //加载驱动
                Class.forName(driverClass);
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * @description:  获取连接
     * @param
     * @return: java.sql.Connection
     */
    public static Connection getConnection() throws SQLException {
        Connection con = null;
        try{
            con = DriverManager.getConnection(url,username,password);
        }catch (Exception e){
            e.printStackTrace();
        }
        return con;
    }
    /**
     * @description:  释放资源
     * @param con
     * @param stat
     * @param res
     */

    public static void close(Connection con, Statement stat , ResultSet res) throws SQLException {
        if(con != null){
            con.close();
        }
        if (stat != null) {
            stat.close();
        }
        if (res != null) {
            res.close();
        }
    }
}

  • JdbcUtil 执行sql语句并返回数据
package com.by.util;

import java.sql.*;

/**
 * @Description: jdbc封装工具类
 * @Version: 1.0
 */
public class JdbcUtils {
    private static Connection con = null;
    private static Statement st = null;
    private static ResultSet rs = null;
    private static PreparedStatement ps = null;
    /**
     * @description: 通用更新封装
     * @param sql    sql语句
     * @param params   传入多参,也可以以数组形式传入
     * @return: java.sql.ResultSet
     */

    public static int update(String sql,Object ...params) throws SQLException {
        int flag = 0;
        try {
            con = Config.getConnection();
            ps = con.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i+1,params[i]);
            }
            System.out.println(ps.toString());
            flag = ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            Config.close(con,ps,null);
        }
        return flag;
    }

    /**
     * @description:  通用查询
     * @param sql
     * @param params
     * @return: java.sql.ResultSet
     */
    public static ResultSet query(String sql, Object ...params) throws SQLException {
        try {
            con = Config.getConnection();
            ps = con.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i + 1, params[i]); //把?替换成实际的参数
            }
            System.out.println(ps.toString());
            rs = ps.executeQuery();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return rs;
    }
}

  • 在resources文件夹添加jdbc.properties配置文件
driverClass = com.mysql.jdbc.Driver
username = root
password = 123456
url = jdbc:mysql://localhost:3306/servlet?characterEncoding=UTF-8

3.5 准备接口和实现类

3.5.1 准备实体类

package com.by.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
    private String sex;
    private Integer age;
    private String address;
    
    public User(String username, String password, String sex, Integer age, String address) {
        this.username = username;
        this.password = password;
        this.sex = sex;
        this.age = age;
        this.address = address;
    }
}

3.5.2 Dao层

  • UserDao接口
package com.by.dao;

import com.by.pojo.User;

import java.sql.SQLException;
import java.util.List;

public interface UserDao {
  //登录
    User login(String username, String password) throws SQLException, Exception;
    //查询所有用户
    List<User> selectUser() throws Exception;
    //添加用户
    boolean addUser(User user) throws Exception;
    //根据id获取用户
    User getUserById(int id) throws Exception;
    //修改用户
    boolean updateUser(User user) throws Exception;
    //删除用户
    boolean delUser(int id) throws Exception;
}

3.5.3 Service层

  • UserService接口
package com.by.service;

import com.by.pojo.User;

import java.util.List;

public interface UserService {
    //登录
    User login(String username, String password) throws Exception;
    //查询所有用户
    List<User> selectUser() throws Exception;
    //添加用户
    boolean addUser(User user) throws Exception;
    //根据id查询用户
    User getUserById(int id) throws Exception;
    //修改用户
    boolean updateUser(User user) throws Exception;
    //删除用户
    boolean delUser(int id) throws Exception;
}

4.基础功能实现

4.1 登录功能

  • 登录表单
<form action="addUser" method="post">
    账户:<input type="text" name="username"><br>
    密码:<input type="text" name="password"><br>
    性别:<input type="text" name="sex"><br>
    年龄:<input type="text" name="age"><br>
    地址:<input type="text" name="address"><br>
    <input type="submit" value="新增">
</form>
  • LoginServlet
//获取前台数据
String username = req.getParameter("username");
 String password = req.getParameter("password");

 //调用service层
 User user = userService.login(username,password);

 //根据是否登录成功跳转页面
 if (user != null){
     //登录成功,跳转数据显示页
     resp.sendRedirect("selectUser");
 }else {
     //登录失败,重新登录
     resp.sendRedirect("login.jsp");
 }
  • Service层
@Override
public User login(String username, String password) throws Exception {
	//无其他业务处理,直接调用dao
    return userDao.login(username,password);
}
  • Dao层
@Override
public User login(String username, String password) throws Exception {
   //编写sql,根据用户名和密码查找用户
   String sql = "select * from user where username=? and password=?";
   ResultSet rs = JdbcUtils.query(sql,username,password);
   if (rs.next()){
       //getUser方法将结果集数据封装成一个user对象
       return getUser(rs);
   }
   return null;
}

4.2 查询所有用户

  • 页面预览
    页面预览

  • select_user.jsp

<%--
  为搭配jsp,暂时使用jstl实现循环添加tb标签
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>芜湖起飞🚀</h1>
    <a href="add_user.jsp">新增</a>
    <table  border="1" width="50%" cellspacing="0">
        <thead>
            <tr>
            <%--表头--%>
                <th>id</th>
                <th>账户</th>
                <th>密码</th>
                <th>性别</th>
                <th>年龄</th>
                <th>地址</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <tr>
            <%--遍历用户集合,生成表格--%>
                <c:forEach items="${userList}" var="user">
                   <tr>
                        <td>${user.id}</td>
                        <td>${user.username}</td>
                        <td>${user.password}</td>
                        <td>${user.sex}</td>
                        <td>${user.age}</td>
                        <td>${user.address}</td>
                        <td style="text-align: center">
		                    <a href="toUpdateUser?id=${user.id}" >修改</a>
		                    <a href="delUser?id=${user.id}"  >删除</a>
		                </td>
                    </tr>
                </c:forEach>
            </tr>
        </tbody>
    </table>
</body>
</html>
  • SelectUserServlet
    显示所有用户信息
 //将获取的所有用户对象存放到集合中
List<User> userList = userService.selectUser();

//将集合数据挂载到请求上
req.setAttribute("userList",userList);

//成功获取数据就跳转到显示页面
req.getRequestDispatcher("select_user.jsp").forward(req,resp);
  • Service层
@Override
public List<User> selectUser() throws Exception {
    //无其他业务处理,直接调用dao
    return userDao.selectUser();
}
  • Dao层
@Override
public List<User> selectUser() throws Exception {
    //编写sql,查询所有用户并按id降序排序
    String sql = "select * from user order by id desc";
    ResultSet rs = JdbcUtils.query(sql);
    List<User> userList = new ArrayList<>();

    //将结果集记录依次取出,并封装成user对象添加到集合中
    while (rs.next()) {
        //将结果集rs当前指针所指记录封装成user对象
        userList.add(getUser(rs));
    }
    return userList;
}

4.3 添加用户

  • add_user.jsp
<form action="addUser" method="post">
    账户:<input type="text" name="username"><br>
    密码:<input type="text" name="password"><br>
    性别:<input type="text" name="sex"><br>
    年龄:<input type="text" name="age"><br>
    地址:<input type="text" name="address"><br>
    <input type="submit" value="新增">
</form>
  • AddUserServlet
    添加新用户,id自增
 //1.获取前台数据
 String username = req.getParameter("username");
 String password = req.getParameter("password");
 String sex = req.getParameter("sex");
 Integer age = Integer.valueOf(req.getParameter("age"));
 String address = req.getParameter("address");

 //2.调用service层添加用户
 boolean flag = userService.addUser(new User(username,password,sex,age,address));
 System.out.println("添加"+(flag?"成功":"失败"));
 //3.跳转到select_User页面显示数据
 resp.sendRedirect("selectUser");
  • Service层
@Override
public boolean addUser(User user) throws Exception {
    //无其他业务处理,直接调用dao
    return userDao.addUser(user);
}
  • Dao层
@Override
public boolean addUser(User user) throws Exception {
    //编写sql,添加用户
    String sql = "insert into user (username,password,sex,age,address) values (?,?,?,?,?)";
    int nums = JdbcUtils.update(sql,user.getUsername(),user.getPassword(),user.getSex(),user.getAge(),user.getAddress());

    //根据影响行数判断是否添加成功,大于0行表示成功
    return nums > 0;
}

4.4 修改用户

4.4.1 数据回显

  • ToUpdateUserServlet

点击修改后通过get方式携带用户id发送请求到ToUpdateUserServlet,然后将从数据库查到的用户数据转发到update_user.jsp页面,实现数据回显。

//获取用户id
int id=Integer.parseInt(req.getParameter("id"));
//通过id获取user对象
User user = userService.getUserById(id);

//将user对象挂载到请求中,转发到修改页
req.setAttribute("user",user);
req.getRequestDispatcher("update_user.jsp").forward(req,resp);
  • service层
@Override
public User getUserById(int id) throws Exception {
    //无其他业务处理,直接调用dao
    return userDao.getUserById(id);
}
  • dao层
    根据id获取user对象
@Override
public User getUserById(int id) throws Exception {
    String sql = "select * from user where id=?";
    ResultSet rs = JdbcUtils.query(sql,id);
    if (rs.next()){
        return getUser(rs);
    }
    return null;
}

4.4.2 修改用户数据

  • update_user.jsp
    进入修改页面,显示servlet页面传来的该用户的数据
<h1>修改用户</h1>
<form action="updateUser" method="post">
  账户:<input type="text" name="username" value="${user.getUsername()}"><br>
  密码:<input type="text" name="password" value="${user.getPassword()}"><br>
  性别:<input type="text" name="sex" value="${user.getSex()}"><br>
  年龄:<input type="text" name="age" value="${user.getAge()}"><br>
  地址:<input type="text" name="address" value="${user.getAddress()}"><br>
  <input type="hidden" name="id" value="${user.getId()}">
  <input type="submit" value="修改">
</form>
  • UpdateUserServlet
    用户提交修改后发送updateUser请求
 //1.获取前台数据
Integer id = Integer.valueOf(req.getParameter("id"));
String username = req.getParameter("username");
String password = req.getParameter("password");
String sex = req.getParameter("sex");
Integer age = Integer.valueOf(req.getParameter("age"));
String address = req.getParameter("address");

//2.调用service层修改用户
boolean flag = userService.updateUser(new User(id,username,password,sex,age,address));
System.out.println("修改"+(flag?"成功":"失败"));
//3.跳转到select_User页面显示数据
resp.sendRedirect("selectUser");
  • Service层
@Override
public boolean updateUser(User user) throws Exception {
    //无其他业务处理,直接调用dao
    return userDao.updateUser(user);
}
  • Dao层
@Override
public boolean updateUser(User user) throws Exception {
    //编写sql语句,修改指定id用户的数据
    String sql = "update user set username=?,password=?,sex=?,age=?,address=?  where id = ?";
    int nums =JdbcUtils.update(sql,user.getUsername(),user.getPassword(),user.getSex(),user.getAge(),user.getAddress(),user.getId());
    
    //根据影响行数判断是否修改成功,大于0行表示成功
    return nums > 0;
}

4.5 删除用户

  • DelUserServlet
//获取用户id
int id=Integer.parseInt(req.getParameter("id"));

//执行删除操作,并返回boolean结果
boolean flag = userService.delUser(id);
System.out.println("删除"+(flag?"成功":"失败"));
//跳转到select_User页面显示数据
resp.sendRedirect("selectUser");
  • Service层
@Override
public boolean delUser(int id) throws Exception {
    //无其他业务处理,直接调用dao
    return userDao.delUser(id);
}
  • Dao层
@Override
public boolean delUser(int id) throws Exception{
    //编写sql语句,根据用户id删除指定用户
    String sql = "delete from user where id=?";
    int nums = JdbcUtils.update(sql,id);

    //根据影响行数判断是否修改成功,大于0行表示成功
    return nums>0;
}

5.拓展功能实现

5.1 判断登录状态

  • 需求:

一些敏感数据和操作需要用户在登录状态才能查看和执行

  • 实现思路:
  1. 用户登录后将user数据通过key-value形式保存在session中
  2. 过滤除登录请求外的所有请求,根据请求中session的参数进行判断
    • 若session中有user参数,则表示已登录,放行请求
    • 若session中没有user参数,则表示未登录,重定向到login.jsp页面
  • 注意事项:

如果连登录页和登录请求一起过滤了,就会陷入无限重定向,因为登录页和登录请求的session中也没有user参数,也会重定向到ogin.jsp页面,但是重定向后也会发起请求,依旧会被过滤。仍没有user参数,就会无限循环下去。

  • LoginFilter
public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        //向下转型
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        if (req.getRequestURI().contains("login") || req.getRequestURI().endsWith("/")){
            //请求包含login或以/结尾,放行
            filterChain.doFilter(request,response);
            System.out.println("请求包含login或以/结尾,放行");
            return;
        }

        //获取session对象,获取user
        HttpSession session = req.getSession();
        Object user = session.getAttribute("user");

        //判断是否已登录
        if (user != null){
            //user有值,已登录,放行
            filterChain.doFilter(request,response);
            System.out.println("已登录,放行");
        }else {
            //未登录,重定向到login.jsp
            resp.sendRedirect("login.jsp");
            System.out.println("未登录,重定向到login.jsp");
        }

    }

    @Override
    public void destroy() {

    }
}
  • 配置Filter
<filter>
    <filter-name>loginFilter</filter-name>
    <filter-class>com.by.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>loginFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

5.2 网站浏览量统计

  • 需求:

统计网站浏览量,并显示用户是第几个访问网站的用户

  • 实现思路:
  1. ServletContext对象作为全局域对象,在整个服务器运行期间都保持存活,可持续记录网站访问量,通过监听器监听ServletContext对象,当ServletContext对象创建时,设置count参数,用于统计访问量。
  2. 每当一个浏览器第一次发送请求到服务器时,会自动生成一个session对象,可在每次创建session对象时算作一次用户访问,通过监听session的创建,动态增加浏览器。
  • AccessCountListener
public class AccessCountListener implements HttpSessionListener, ServletContextListener {
    /**
     * session创建时调用(浏览器第一次访问服务器,或session失效后重新访问时)
     * @param se the HttpSessionEvent containing the session
     */
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        //获取ServletContext对象
        ServletContext servletContext = se.getSession().getServletContext();
        Integer count = (Integer) servletContext.getAttribute("count");
        //每次调用该方法,访问量count+1
        servletContext.setAttribute("count",++count);

    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {

    }

    /**
     * 创建ServletContext对象时调用(服务器开启时)
     * @param sce the ServletContextEvent containing the ServletContext
     * that is being initialized
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //获取ServletContext对象
        ServletContext servletContext = sce.getServletContext();
        //添加count参数,记录访问量
        servletContext.setAttribute("count", 0);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {

    }
}
  • 配置Listener
<listener>
    <listener-class>com.by.Listener.AccessCountListener</listener-class>
</listener>
  • 20
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

这河里吗l

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值