基于SpringMVC+Maven+thymeleaf的简易用户管理系统(RESTFul风格)

一、简介

最近在学SpringMVC,碰到一个很适合新手的十分简易的小练习,在这里分享一下。用的是spring6+tomcat10+jdk17。

页面展示:

 

 

 

二、环境搭建

先按照如下结构搭建出web目录结构

 

1、pom.xml:设置打包方式为war包,同时添加如下依赖

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>6.1.4</version>
        </dependency>

        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>6.0.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.5.3</version>
        </dependency>

        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring6</artifactId>
            <version>3.1.2.RELEASE</version>
        </dependency>
    </dependencies>

2、web.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--字符编码过滤器-->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--此过滤器可以帮助我们将POST请求转换成PUT/DELETE请求-->
    <!--
        一定要在字符过滤器之后配置
            因为HiddenHttpMethodFilter底层执行时会调用request.getParameter()方法,如果在字符过滤器之前配置的话,会导致乱码
    -->
    <filter>
        <filter-name>hiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>hiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--前端控制器-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>



</web-app>

3、springmvc.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--组件扫描-->
    <context:component-scan base-package="com.zsx.usermgt"/>

    <!--视图解析-->
    <bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver">
        <property name="characterEncoding" value="UTF-8"/>
        <property name="order" value="1"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring6.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML"/>
                        <property name="characterEncoding" value="UTF-8"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

    <!--
        视图控制器
            path: "/test" @RequestMapping中的请求路径
                view-name: "test" 最后返回的逻辑试图名称
            作用:
                如果一个Controller上的方法只是为了完成视图跳转,没有任何业务代码,那么这个Controller可以不写
                直接在springmvc.xml文件中添加 <mvc:view-controller>即可
            注意:此配置会使整个项目的所有注解失效,所以需要加上 <mvc:annotation-driven/> ,手动开启注解驱动
    -->
    <mvc:view-controller path="/" view-name="user_index"/>
    <mvc:view-controller path="/toAdd" view-name="user_add"/>

    <!--注解驱动-->
    <mvc:annotation-driven/>

    <!--处理静态资源,开启默认的Servlet处理-->
    <mvc:default-servlet-handler/>
</beans>

三、静态资源以及html文件

css文件以及html文件(准确来说是thymeleaf模版字符串,并不是真正的heml文件,相信小伙伴们在学springmvc时或者thymeleaf时老师会讲的,这里我就不多解释了)

user.css

.header {
  background-color: #f2f2f2;
  padding: 20px;
  text-align: center;
}

ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #333;
}

li {
  float: left;
}

li a {
  display: block;
  color: white;
  text-align: center;
  padding: 14px 16px;
  text-decoration: none;
}

li a:hover:not(.active) {
  background-color: #111;
}

.active {
  background-color: #4CAF50;
}

form {
  width: 50%;
  margin: 0 auto;
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

label {
  display: block;
  margin-bottom: 8px;
}

input[type="text"], input[type="email"], select {
  width: 100%;
  padding: 6px 10px;
  margin: 8px 0;
  box-sizing: border-box;
  border: 1px solid #555;
  border-radius: 4px;
  font-size: 16px;
}

button[type="submit"] {
  padding: 10px;
  background-color: #4CAF50;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button[type="submit"]:hover {
  background-color: #3e8e41;
}

table {
  border-collapse: collapse;
  width: 100%;
}

th, td {
  border: 1px solid #ddd;
  padding: 8px;
  text-align: left;
}

th {
  background-color: #f2f2f2;
}

tr:nth-child(even) {
  background-color: #f2f2f2;
}

.header {
  background-color: #f2f2f2;
  padding: 20px;
  text-align: center;
}

a {
  text-decoration: none;
  color: #333;
}

.add-button {
  margin-bottom: 20px;
  padding: 10px;
  background-color: #4CAF50;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.add-button:hover {
  background-color: #3e8e41;
}

user_index.html(user_index.html这个页面准备完成后,建议大家启动Tomcat服务器,测试一下可不可以访问到user_index界面,防止后续错误越积越多不利于调试)

<!DOCTYPE html>
<html lang="en" xmlns:th="www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>用户管理系统</title>
  <link rel="stylesheet" th:href="@{/static/css/user.css}" type="text/css"></link>
</head>
<body>
  <div class="header">
    <h1>用户管理系统</h1>
  </div>
  <ul>
    <li><a class="active" th:href="@{/user}">用户列表</a></li>
  </ul>
</body>
</html>

user_list.html

<!DOCTYPE html>
<html lang="en" xmlns:th="www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>用户列表</title>
  <link rel="stylesheet" th:href="@{/static/css/user.css}" type="text/css"></link>
</head>
<body>
  <div class="header">
    <h1>用户列表</h1>
  </div>
  <div class="add-button-wrapper">
    <a class="add-button" th:href="@{/toAdd}">新增用户</a>
  </div>
  <table>
    <thead>
      <tr>
        <th>编号</th>
        <th>用户名</th>
        <th>性别</th>
        <th>邮箱</th>
        <th>操作</th>
      </tr>
    </thead>
	<tbody>
      <tr th:each="user : ${users}">
        <td th:text="${user.id}"></td>
        <td th:text="${user.username}"></td>
        <td th:text="${user.sex == 1 ? '男' : '女'}"></td>
        <td th:text="${user.email}"></td>
        <td>
          <a th:href="@{'/user/' + ${user.id}}">修改</a>
          <a th:href="@{'/user/' + ${user.id}}" onclick="del(event)">删除</a>
        </td>
      </tr>

    </tbody>
  </table>

  <div style="display: none">
    <form id="delForm" method="post">
      <input type="hidden" name="_method" value="delete">
    </form>
  </div>

<script>
  function del(event){
    let delForm = document.getElementById("delForm");
    delForm.action = event.target.href;
    if(window.confirm("您确定要删除该用户吗")) {
      delForm.submit();
    }
    //阻止超链接的默认跳转行为
    event.preventDefault();
  }
</script>
</body>
</html>

user_add.html

<!DOCTYPE html>
<html lang="en" xmlns:th="www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>新增用户</title>
  <link rel="stylesheet" th:href="@{/static/css/user.css}" type="text/css"></link>
</head>
<body>
  <h1>新增用户</h1>
  <form th:action="@{/user}" method="post">
    <label>用户名:</label>
    <input type="text" name="username" required>

    <label>性别:</label>
    <select name="gender" required>
      <option value="">-- 请选择 --</option>
      <option value="1">男</option>
      <option value="0">女</option>
    </select>

    <label>邮箱:</label>
    <input type="email" name="email" required>

	<button type="submit">保存</button>
  </form>
</body>
</html>

user_edit.html

<!DOCTYPE html>
<html lang="en" xmlns:th="www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>修改用户</title>
  <link rel="stylesheet" th:href="@{/static/css/user.css}" type="text/css"></link>
</head>
<body>
  <h1>修改用户</h1>
  <form th:action="@{/user}" method="post">

    <!--隐藏域:设置请求方式-->
    <input type="hidden" name="_method" value="put">
    <!--隐藏域:提交id-->
    <input type="hidden" name="id" th:value="${user.id}">

    <label>用户名:</label>
    <input type="text" name="username" th:value="${user.username}" required>

    <label>性别:</label>
    <select name="sex" required>
      <option value="">-- 请选择 --</option>
      <option value="1" th:field="${user.sex}">男</option>
      <option value="0" th:field="${user.sex}">女</option>
    </select>

    <label>邮箱:</label>
    <input type="email" name="email" th:value="${user.email}" required>

    <button type="submit">修改</button>
  </form>
</body>
</html>

四、主要源代码文件 

先按下图搭建出目录结构

UserController.java

package com.zsx.usermgt.controller;

import com.zsx.usermgt.dao.UserDao;
import com.zsx.usermgt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author Z-熙玉
 * @version 1.0
 */
@Controller
public class UserController {

    @Autowired
    private UserDao userDao;

    @GetMapping(value = "/user")
    public String list(Model model) {
        List<User> users = userDao.selectAll();
        model.addAttribute("users",users);
        return "user_list";
    }

    @PostMapping(value = "/user")
    public String save(User user) {
        userDao.insert(user);
        //重定向到用户列表界面
        return "redirect:/user";
    }

    @GetMapping(value = "/user/{id}")
    public String detail(@PathVariable("id") Long id, Model model) {
        User user = userDao.selectById(id);
        model.addAttribute("user",user);
        return "user_edit";
    }

    @PutMapping("/user")
    public String modify(User user) {
        userDao.update(user);
        //重定向到用户列表界面
        return "redirect:/user";
    }

    @DeleteMapping(value = "/user/{id}")
    public String del(@PathVariable("id") Long id) {
        userDao.deleteById(id);
        //重定向到用户列表界面
        return "redirect:/user";
    }

}

 UserDao.java(因为没有连接数据库,这里就用list集合模拟一下数据的增删改查,如果学过mybatis大家可以尝试自己整合一下)

package com.zsx.usermgt.dao;

import com.zsx.usermgt.pojo.User;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Z-熙玉
 * @version 1.0
 */
@Repository
public class UserDao {

    private static List<User> users = new ArrayList<>();

    static {
        //类加载时初始化数据
        User user1 = new User(1001L,"张三",1,"zhangsan@zxy.com");
        User user2 = new User(1002L,"孙悟空",1,"sunwukong@zxy.com");
        User user3 = new User(1003L,"唐僧",1,"tangseng@zxy.com");
        User user4 = new User(1004L,"猪八戒",1,"zhubajie@zxy.com");
        User user5 = new User(1005L,"沙僧",1,"shaseng@zxy.com");
        User user6 = new User(1006L,"白骨精",0,"baigujing@zxy.com");
        users.add(user1);
        users.add(user2);
        users.add(user3);
        users.add(user4);
        users.add(user5);
        users.add(user6);
    }

    /**
     * 查询所有用户信息
     * @return
     */
    public List<User> selectAll() {
        return users;
    }

    /**
     * 新增用户
     * @param user
     */
    public void insert(User user) {
        //生成id(因为没有连接数据库,这里就手动生成了,连接了数据库可以使用数据库自增id)
        Long id = generateId();
        user.setId(id);
        users.add(user);
    }

    /**
     * 手动生成id
     * 将最大的id值 + 1 作为新增用户的id
     */
    public Long generateId() {
        Long maxId = users.stream().map(user -> user.getId()).reduce((id1, id2) -> id1 > id2 ? id1 : id2).get();
        return maxId + 1;
    }

    /**
     * 根据id查询用户信息
     * @param id
     * @return
     */
    public User selectById(Long id) {
        return users.stream().filter(user -> user.getId().equals(id)).findFirst().get();
    }

    /**
     * 修改用户信息
     * @param user
     */
    public void update(User user) {
        for (int i = 0; i < users.size(); i++) {
            if(users.get(i).getId().equals(user.getId())) {
                users.set(i,user);
                return;
            }
        }
    }

    /**
     * 根据id删除用户信息
     * @param id
     */
    public void deleteById(Long id) {
        for (int i = 0; i < users.size(); i++) {
            if(users.get(i).getId().equals(id)) {
                users.remove(i);
                return;
            }
        }
    }
}

User.java

package com.zsx.usermgt.pojo;

/**
 * @author Z-熙玉
 * @version 1.0
 */
public class User {

    private Long id;
    private String username;
    private Integer sex;
    private String email;

    public User(Long id, String username, Integer sex, String email) {
        this.id = id;
        this.username = username;
        this.sex = sex;
        this.email = email;
    }

    public User() {
    }

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

    public Long getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

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

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

到这里就可以了,可以启动Tomcat来试一下啦,这个小练习还是很简单的,想必看到这篇文章的有不少初学者,大家可以看完之后,自己动手做一下,还是有不少收获的。如果想要连接数据库的,大家可以在评论区评论,人多的话,过几天出个整合mybatis的。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值