一、简介
最近在学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的。