一、前期准备工作
- 熟悉thymeleaf语法
- 熟悉spring、springMVC里面的相关操作
- 熟悉拦截器
- 熟悉springboot搭建项目过程
- 了解Bootstrap
- 准备一套web静态页面(登录页面、信息展示主页面)
- IDEA开发工具
二、项目整体思路
项目整体思路1. 搭建项目并正常访问
构建一个springboot项目,并把静态资源放入到项目中
- css、js、img等资源放入到static目录
因为本项目使用的是cdn的方式,即在对应的html页面中对应位置插入以下内容即可
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<!-- 新 Bootstrap4 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css">
<!-- popper.min.js 用于弹窗、提示、下拉菜单 -->
<script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
<!-- 最新的 Bootstrap4 核心 JavaScript 文件 -->
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
- html等模板代码放入到template目录
这里使用thymeleaf语法
- login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<title>登陆页面</title>
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<!-- 新 Bootstrap4 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css">
<!-- popper.min.js 用于弹窗、提示、下拉菜单 -->
<script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
<!-- 最新的 Bootstrap4 核心 JavaScript 文件 -->
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
<script>
$(function(){
$("button:contains('删除')").click(function(){
$.post("/user/delete",{"id":this.id});
$(this).parent().parent().remove();
});
$("button:contains('修改')").click(function(){
//弹出修改窗口
$('#myModal').modal();
//把User对象转成json对象
var jsonObj = JSON.parse($(this).attr("id"));
//为修改页面进行赋值
$('#txt_id').val(jsonObj['id']);
$('#txt_username').val(jsonObj['username']);
$('#txt_password').val(jsonObj['password']);
$('#txt_name').val(jsonObj['name']);
$('#txt_userSex').val(jsonObj['userSex']);
});
})
//添加的方法
function add() {
//弹出新建窗口
$('#myModal1').modal();
}
</script>
</head>
<body>
<div class="container">
<table class="table table-dark table-hover">
<thead>
<tr>
<th>id</th>
<th>用户名</th>
<th>密码</th>
<th>真实姓名</th>
<th>性别</th>
<th>删除</th>
<th>修改</th>
</tr>
</thead>
<tbody>
<tr th:each="users:${list}">
<td th:text="${users.id}"></td>
<td th:text="${users.username}"></td>
<td th:text="${users.password}"></td>
<td th:text="${users.name}"></td>
<td th:text="${users.userSex}"></td>
<th><button th:id="${users.id}" onclick="return confirm('你确定要删除这条数据吗?')">删除</button></th>
<th><button th:id="${users}">修改</button></th>
</tr>
</tbody>
</table>
<button onclick="add()">添加</button>
<!--添加页面-->
<div class="modal fade" id="myModal1" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form method="post" action="#" th:action="@{/add.do}">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel1">添加</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="txt_username">用户名</label>
<input type="text" name="username" class="form-control" placeholder="用户名">
</div>
<div class="form-group">
<label for="txt_password">密码</label>
<input type="password" name="password" class="form-control" placeholder="密码">
</div>
<div class="form-group">
<label for="txt_name">真实姓名</label>
<input type="text" name="name" class="form-control" placeholder="真实姓名">
</div>
<div class="form-group">
<label for="txt_userSex">性别</label>
<input type="text" name="userSex" class="form-control" placeholder="性别">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>关闭</button>
<input type="submit" value="保存" id="btn_submit1" class="btn btn-primary" /><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>
</div>
</form>
</div>
</div>
</div>
<!--修改页面-->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form method="post" action="#" th:action="@{/update.do}">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">修改</h4>
</div>
<div class="modal-body">
<input type="text" name="id" id="txt_id" hidden="true">
<div class="form-group">
<label for="txt_username">用户名</label>
<input type="text" name="username" class="form-control" id="txt_username" placeholder="用户名">
</div>
<div class="form-group">
<label for="txt_password">密码</label>
<input type="password" name="password" class="form-control" id="txt_password" placeholder="密码">
</div>
<div class="form-group">
<label for="txt_name">真实姓名</label>
<input type="text" name="name" class="form-control" id="txt_name" placeholder="真实姓名">
</div>
<div class="form-group">
<label for="txt_userSex">性别</label>
<input type="text" name="userSex" class="form-control" id="txt_userSex" placeholder="性别">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>关闭</button>
<input type="submit" value="保存" id="btn_submit" class="btn btn-primary" /><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
- list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<title>登陆页面</title>
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<!-- 新 Bootstrap4 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css">
<!-- popper.min.js 用于弹窗、提示、下拉菜单 -->
<script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
<!-- 最新的 Bootstrap4 核心 JavaScript 文件 -->
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
<script>
$(function(){
$("button:contains('删除')").click(function(){
$.post("/user/delete",{"id":this.id});
$(this).parent().parent().remove();
});
$("button:contains('修改')").click(function(){
//弹出修改窗口
$('#myModal').modal();
//把User对象转成json对象
var jsonObj = JSON.parse($(this).attr("id"));
//为修改页面进行赋值
$('#txt_id').val(jsonObj['id']);
$('#txt_username').val(jsonObj['username']);
$('#txt_password').val(jsonObj['password']);
$('#txt_name').val(jsonObj['name']);
$('#txt_userSex').val(jsonObj['userSex']);
});
})
//添加的方法
function add() {
//弹出新建窗口
$('#myModal1').modal();
}
</script>
</head>
<body>
<div class="container">
<table class="table table-dark table-hover">
<thead>
<tr>
<th>id</th>
<th>用户名</th>
<th>密码</th>
<th>真实姓名</th>
<th>性别</th>
<th>删除</th>
<th>修改</th>
</tr>
</thead>
<tbody>
<tr th:each="users:${list}">
<td th:text="${users.id}"></td>
<td th:text="${users.username}"></td>
<td th:text="${users.password}"></td>
<td th:text="${users.name}"></td>
<td th:text="${users.userSex}"></td>
<th><button th:id="${users.id}" onclick="return confirm('你确定要删除这条数据吗?')">删除</button></th>
<th><button th:id="${users}">修改</button></th>
</tr>
</tbody>
</table>
<button onclick="add()">添加</button>
<!--添加页面-->
<div class="modal fade" id="myModal1" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form method="post" action="#" th:action="@{/add.do}">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel1">添加</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="txt_username">用户名</label>
<input type="text" name="username" class="form-control" placeholder="用户名">
</div>
<div class="form-group">
<label for="txt_password">密码</label>
<input type="password" name="password" class="form-control" placeholder="密码">
</div>
<div class="form-group">
<label for="txt_name">真实姓名</label>
<input type="text" name="name" class="form-control" placeholder="真实姓名">
</div>
<div class="form-group">
<label for="txt_userSex">性别</label>
<input type="text" name="userSex" class="form-control" placeholder="性别">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>关闭</button>
<input type="submit" value="保存" id="btn_submit1" class="btn btn-primary" /><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>
</div>
</form>
</div>
</div>
</div>
<!--修改页面-->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form method="post" action="#" th:action="@{/update.do}">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">修改</h4>
</div>
<div class="modal-body">
<input type="text" name="id" id="txt_id" hidden="true">
<div class="form-group">
<label for="txt_username">用户名</label>
<input type="text" name="username" class="form-control" id="txt_username" placeholder="用户名">
</div>
<div class="form-group">
<label for="txt_password">密码</label>
<input type="password" name="password" class="form-control" id="txt_password" placeholder="密码">
</div>
<div class="form-group">
<label for="txt_name">真实姓名</label>
<input type="text" name="name" class="form-control" id="txt_name" placeholder="真实姓名">
</div>
<div class="form-group">
<label for="txt_userSex">性别</label>
<input type="text" name="userSex" class="form-control" id="txt_userSex" placeholder="性别">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>关闭</button>
<input type="submit" value="保存" id="btn_submit" class="btn btn-primary" /><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
- 修改配置文件
- 修改application.properties
# 设置缓存不生效
spring.thymeleaf.cache=false
- 配置pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.lazyfennec</groupId>
<artifactId>springboot-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 新建Controller
package cn.lazyfennec.springboot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Author: Neco
* @Description:
* @Date: create in 2022/4/25 21:53
*/
@Controller
public class UserController {
@RequestMapping("/login")
public String test() {
return "login";
}
}
-
启动并测试是否正常
访问测试
2. 设置主页的默认访问方式
通过修改WebMvcConfigure的默认设置来指定页面的默认访问方式
- 构建一个配置类,实现WebMvcConfigurer接口,重写addViewControllers方法;
- 添加自定义页面的默认主页映射:addViewController().setViewName()
package cn.lazyfennec.springboot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Author: Neco
* @Description:
* @Date: create in 2022/4/25 22:28
*/
@Configuration
public class WebMvcConfigure implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login.html");
}
}
- 再访问 http://localhost:8080/
http://localhost:8080/
3. 登录功能
- 完成登录页面的修改
- 完成后台编码
a. 实体类的构建
b. repository类以及其实现类的书写
c. controller类的登录功能实现 - 完成登录失败的功能提示
- 修改UserController类
package cn.lazyfennec.springboot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.thymeleaf.util.StringUtils;
/**
* @Author: Neco
* @Description:
* @Date: create in 2022/4/25 21:53
*/
@Controller
public class UserController {
@RequestMapping("/user/login")
public String login(String username, String password, ModelMap modelMap) {
// 模拟登录
if(!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)
&& "admin".equals(username) && "admin".equals(password)) {
return "list";
} else {
modelMap.addAttribute("login_error", "用户名或密码错误");
return "login";
}
}
}
重启测试
4. 数据展示、删除
- 数据展示页面的修改/添加数据删除的js代码;
- 后台编码
a. controller里面加上对应的方法;
b. repository里面加上对应的方法; - 测试是否生效
- 构建实体类User
package cn.lazyfennec.springboot.entity;
/**
* @Author: Neco
* @Description:
* @Date: create in 2022/4/25 22:47
*/
public class User {
private int id;
private String username;
private String password;
private String name;
private String userSex;
public User() {
}
public User(int id, String username, String password, String name, String userSex) {
this.id = id;
this.username = username;
this.password = password;
this.name = name;
this.userSex = userSex;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
}
- 修改UserController
package cn.lazyfennec.springboot.controller;
import cn.lazyfennec.springboot.entity.User;
import cn.lazyfennec.springboot.repository.UsersRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.thymeleaf.util.StringUtils;
import java.util.List;
/**
* @Author: Neco
* @Description:
* @Date: create in 2022/4/25 21:53
*/
@Controller
public class UserController {
@Autowired
private UsersRepository usersRepository;
@RequestMapping("/user/login")
public String login(String username, String password, ModelMap modelMap) {
// 模拟登录
if(!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)
&& "admin".equals(username) && "admin".equals(password)) {
return "redirect:/user/list";
} else {
modelMap.addAttribute("login_error", "用户名或密码错误");
return "login";
}
}
@RequestMapping("/user/list")
public String findAll(ModelMap modelMap) {
List<User> users = usersRepository.findAll();
modelMap.addAttribute("list", users);
return "list";
}
@RequestMapping("/user/delete")
public String deleteUserById(int id) {
int result = usersRepository.deleteUserById(id);
return "list";
}
}
- 创建UsersRepository 和 UsersRepositoryImpl
package cn.lazyfennec.springboot.repository;
import cn.lazyfennec.springboot.entity.User;
import java.util.List;
public interface UsersRepository {
List<User> findAll();
int deleteUserById(int id);
}
package cn.lazyfennec.springboot.repository.impl;
import cn.lazyfennec.springboot.entity.User;
import cn.lazyfennec.springboot.repository.UsersRepository;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* @Author: Neco
* @Description:
* @Date: create in 2022/4/25 22:50
*/
@Repository
public class UsersRepositoryImpl implements UsersRepository {
// 模拟数据库
static List<User> users = new ArrayList<>();
static {
Collections.addAll(users,
new User(1001, "zhangsan", "123456", "张三", "男"),
new User(1002, "lisi", "123456", "李四", "女"),
new User(1003, "wangwu", "123456", "王五", "男"),
new User(1004, "maliu", "123456", "马六", "女")
);
}
@Override
public List<User> findAll() {
return users;
}
@Override
public int deleteUserById(int id) {
Iterator<User> iterator = users.iterator();
while (iterator.hasNext()) {
User user = iterator.next();
if(user.getId() == id) {
iterator.remove();
return 1;
}
}
return 0;
}
}
-
重启并且测试
image.png
5. 拦截器功能
- 书写一个自定义拦截器类,功能就是检测是否登录
package cn.lazyfennec.springboot.intercept;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author: Neco
* @Description:
* @Date: create in 2022/4/25 23:23
*/
public class LoginHandlerIntercept implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object username = request.getSession().getAttribute("username");
if (username != null) {
return true;
} else {
request.setAttribute("login_error", "请先登录");
request.getRequestDispatcher("/").forward(request, response);
return false;
}
}
}
- 在WebMvcConfigure类里重写添加拦截器的方法,并进行业务的书写
package cn.lazyfennec.springboot.config;
import cn.lazyfennec.springboot.intercept.LoginHandlerIntercept;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Author: Neco
* @Description:
* @Date: create in 2022/4/25 22:28
*/
@Configuration
public class WebMvcConfigure implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login.html");
}
/**
* 配置拦截器
*
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerIntercept())
.addPathPatterns("/**")
.excludePathPatterns("/", "/login.html", "/user/login", "/css/**", "/js/**", "/img/**");
}
}
@RequestMapping("/user/login")
public String login(String username, String password, ModelMap modelMap, HttpSession session) {
// 模拟登录
if(!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)
&& "admin".equals(username) && "admin".equals(password)) {
session.setAttribute("username", username); // 修改逻辑,登录后将username存到session中
return "redirect:/user/list";
} else {
modelMap.addAttribute("login_error", "用户名或密码错误");
return "login";
}
}
- 测试是否生效
测试访问 http://localhost:8080/user/list
测试访问 http://localhost:8080/user/list
更多知识,请点击关注查看我的主页信息哦~
网友评论