导航:

pre:  1.系统功能和架构介绍

next:3.用户登录

只挑重点的讲,具体的请看项目源码。

1.项目源码:

需要源码的朋友,请捐赠任意金额后留下邮箱发送:)

2.添加依赖

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!--spring security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency> <!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> <dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency> <!--SpringBoot热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency> <!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency> <!--JDBC-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency> <!--commons-lang3-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency> <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</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>
<resources>
<!-- fonts file cannot use filter as the data structure of byte file will be changed via filter -->
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>static/layui/font/**</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
</build>

3.配置文件application.yml

server:
port: 8080
servlet:
context-path:
session:
timeout: 7200s
spring:
mvc:
static-path-pattern: /**
date-format: yyyy-MM-dd
favicon:
enabled: true
thymeleaf:
encoding: UTF-8
cache: false
mode: HTML
prefix: classpath:/templates/
suffix: .html
# 数据源
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: root123
url: jdbc:mysql://localhost:3306/bookman?characterEncoding=utf-8&useSSL=false
type: com.zaxxer.hikari.HikariDataSource
hikari:
pool-name: BookHikariPool
maximum-pool-size: 12
connection-timeout: 60000
connection-test-query: SELECT 1
servlet:
multipart:
max-request-size: 100MB
max-file-size: 50MB
# mybatis
mybatis:
mapper-locations: classpath:mybatis/mapper/*.xml
configuration:
map-underscore-to-camel-case: true
# 文件上传路径
web:
upload:
path: D:/upload/

4.导入数据库

数据库脚本在:src/resources/bookman.sql

创建数据库:bookman  编码:UTF-8

执行SQL语句

5.工具类

5.1 文件上传

public class UploadUtils {
public static String upload(MultipartFile file, String path, String fileName) throws Exception {
// 生成新的文件名
String realPath = path + "/" + UUID.randomUUID().toString().replace("-", "") + fileName.substring(fileName.lastIndexOf("."));
File dest = new File(realPath);
// 判断文件父目录是否存在
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdir();
}
// 保存文件
file.transferTo(dest);
return dest.getName();
}
}

5.2 MD5

/**
* md5工具类
*/
public class MD5Util {
public static final int time = 5; public static final String SALT = "springsecurity"; /**
* 密码加密方法
*
* @param password
* @return
*/
public static String encode(String password) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK).");
}
try {
for (int i = 0; i < time; i++) {
byte[] bytes = digest.digest((password + SALT).getBytes("UTF-8"));
password = String.format("%032x", new BigInteger(1, bytes));
}
return password;
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK).");
}
} public static void main(String[] args) {
System.out.println(MD5Util.encode("admin"));
}
}

5.3 spring security

/**
* @Description: spring security工具类
* @Author laoxu
* @Date 2019/5/11 17:20
**/
public class SecurityUtil {
public static String getLoginUser(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication instanceof AnonymousAuthenticationToken)) {
String currentUserName = authentication.getName();
return currentUserName;
}
return "";
}
}

6.配置类

6.1 MVC配置

/**  mvc配置,例如:资源映射、视图解析、拦截器等
* @author laoxu
* @create 2018-10-23
**/ @Configuration
public class WebMvcConfig implements WebMvcConfigurer { @Autowired
SessionTimeoutInterceptor sessionTimeoutInterceptor; @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("/assets/ckeditor/**").
addResourceLocations("classpath:/static/assets/ckeditor/").
setCachePeriod(2592000);
} @Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index").setViewName("index");
registry.addViewController("/login").setViewName("login");
registry.addViewController("/success").setViewName("success");
registry.addViewController("/admin").setViewName("admin");
registry.addViewController("/book").setViewName("book");
registry.addViewController("/bookAdd").setViewName("bookAdd");
registry.addViewController("/bookEdit").setViewName("bookEdit");
registry.addViewController("/bookBorrow").setViewName("bookBorrow");
registry.addViewController("/bookBorrowAdd").setViewName("bookBorrowAdd");
registry.addViewController("/bookBorrowEdit").setViewName("bookBorrowEdit");
registry.addViewController("/bookReBorrow").setViewName("bookReBorrow");
registry.addViewController("/bookReBorrowEdit").setViewName("bookReBorrowEdit");
registry.addViewController("/bookReturn").setViewName("bookReturn");
registry.addViewController("/bookCategory").setViewName("bookCategory");
registry.addViewController("/bookLanguage").setViewName("bookLanguage");
registry.addViewController("/bookPublisher").setViewName("bookPublisher");
registry.addViewController("/bookShelf").setViewName("bookShelf");
registry.addViewController("/bookReader").setViewName("bookReader");
registry.addViewController("/bookStat").setViewName("bookStat");
} @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(sessionTimeoutInterceptor).addPathPatterns("/**").
excludePathPatterns("/api/book/list","/bookDetail/*","/","/index","/login","/static/**","/logout");
}
}

6.2 统一返回结构

/**
* 请求返回结果
*
* @author laoxu
* @create 2018-10-23
**/
public class Result<T> {
private boolean success = true;
private int code = ErrorStatus.OK.getCode();
private String message = "";
private T data; public static <T> Result<T> newInstance() {
return new Result<T>();
} public Result() { } public Result(T data) {
this.data = data;
} public Result(ErrorStatus status) {
this.message = status.getMessage();
this.code = status.getCode();
} public Result(String message) {
this.message = message;
} public Result(int code, String message) {
this.message = message;
this.code = code;
} public Result(int code, String message, T data) {
this.message = message;
this.code = code;
this.data = data;
} public Result<T> status(ErrorStatus status) {
this.message = message;
this.code = code;
return this;
} public Result<T> ok() {
success = true;
return this;
} public Result<T> fail() {
success = false;
return this;
} public Result<T> message(String message) {
this.message = message;
return this;
} public Result<T> data(T data) {
this.data = data;
return this;
} public Result<T> code(int code) {
this.code = code;
return this;
} public boolean isSuccess() {
return success;
} // 省略get,set
}
/**
* @Description: 响应消息体
* @Author laoxu
* @Date 2019/12/21 9:50
**/
public class ResultBean<T> {
/**响应编码*/
private int code;
/**响应消息*/
private String msg;
/**数据总量*/
private int count;
/**数据*/
private T data; public ResultBean() {
} public ResultBean(int code, String msg, int count, T data) {
super();
this.code = code;
this.msg = msg;
this.count = count;
this.data = data;
} @Override
public String toString() {
return "R [code=" + code + ", msg=" + msg + ", count=" + count + ", data=" + data + "]";
} // 省略get,set
}
/**
* 返回结果工具类
*
* @author laoxu
* @create 2018-10-23
**/
public class ResultUtil {
public static boolean isOk(Result<?> result){
return null != result && result.getCode() == ErrorStatus.OK.getCode();
} public static <T> Result<T> ok(){
return new Result<T>(ErrorStatus.OK);
} public static <T> Result<T> ok(T data){
return new Result<T>(ErrorStatus.OK.getCode(), ErrorStatus.OK.getMessage(), data);
} public static <T> Result<T> fail(){
return new Result<T>(ErrorStatus.BAD_REQUEST).fail();
} public static <T> Result<T> status(ErrorStatus status){
return new Result<T>(status.getCode(), status.getMessage()).fail();
} public static <T> Result<T> fail(ErrorStatus status){
return new Result<T>(status.getCode(), status.getMessage()).fail();
} public static <T> Result<T> fail(String message){
return fail(ErrorStatus.BAD_REQUEST.getCode(), message, (T)null).fail();
} public static <T> Result<T> fail(int code, String message){
return new Result<T>(code, message).fail();
} public static <T> Result<T> fail(int code ,String message, T data){
return new Result<T>(code, message, data).fail();
} public static <T> Result<T> notfound(){
return new Result<T>(ErrorStatus.NOT_FOUND).fail();
} }

6.3 错误信息封装

/**
* 错误代号和信息
*
* @author laoxu
* @create 2018-10-23
**/
public enum ErrorStatus {
OK(200, "OK"),
FOUND(302, "Found"),
BAD_REQUEST(400, "Bad Request"),
UNAUTHORIZED(401, "Unauthorized"),
FORBIDDEN(403, "Forbidden"),
NOT_FOUND(404, "Not Found"),
INTERNAL_SERVER_ERROR(500, "Internal Server Error"),
SERVICE_UNAVAILABLE(503, "Service Unavailable"); private final int code; private final String message; ErrorStatus(int code, String message) {
this.code = code;
this.message = message;
} public int getCode() {
return code;
} public String getMessage() {
return message;
}
}

6.4 自定义异常

/**
* @Description: 异常处理器
* @Author laoxu
* @Date 2019/7/3 22:14
**/
@ControllerAdvice
public class ExceptionsHandler {
@ResponseBody
@ExceptionHandler(UnAuthorizedException.class)//可以直接写@ExceptionHandler,不指明异常类,会自动映射
public Result<String> customGenericExceptionHnadler(UnAuthorizedException exception){ //还可以声明接收其他任意参数
return ResultUtil.fail(Integer.valueOf(exception.getErrorCode()),exception.getErrorMessage());
}
}

7.静态资源

添加 layui文件

Spring Boot图书管理系统项目实战-2.项目搭建的更多相关文章

  1. 图书-技术-SpringBoot:《Spring Boot 企业级应用开发实战》

    ylbtech-图书-技术-SpringBoot:<Spring Boot 企业级应用开发实战> Spring Boot 企业级应用开发实战,全书围绕如何整合以 Spring Boot 为 ...

  2. 《Spring Boot 入门及前后端分离项目实践》系列介绍

    课程计划 课程地址点这里 本课程是一个 Spring Boot 技术栈的实战类课程,课程共分为 3 个部分,前面两个部分为基础环境准备和相关概念介绍,第三个部分是 Spring Boot 项目实践开发 ...

  3. Vue+Spring Boot 前后端分离的商城项目开源啦!

    新蜂商城 Vue 移动端版本开源啦! 去年开源新蜂商城项目后,就一直在计划这个项目 Vue 版本的改造,2020 年开始开发并且自己私下一直在测试,之前也有文章介绍过测试过程和存在的问题,修改完成后, ...

  4. Spring Boot会员管理系统——处理文件上传

    温馨提示 Spring Boot会员管理系统的中,需要涉及到Spring框架,SpringMVC框架,Hibernate框架,thymeleaf模板引擎.所以,可以学习下这些知识.当然,直接入门的话使 ...

  5. Spring Boot 从入门到实战汇总

    之前写过几篇spring boot入门到实战的博文,因为某些原因没能继续. 框架更新迭代很快,之前还是基于1.x,现在2.x都出来很久了.还是希望能从基于该框架项目开发的整体有一个比较系统的梳理,于是 ...

  6. spring boot / cloud (十八) 使用docker快速搭建本地环境

    spring boot / cloud (十八) 使用docker快速搭建本地环境 在平时的开发中工作中,环境的搭建其实一直都是一个很麻烦的事情 特别是现在,系统越来越复杂,所需要连接的一些中间件也越 ...

  7. Spring Boot从入门到实战:整合Web项目常用功能

    在Web应用开发过程中,一般都涵盖一些常用功能的实现,如数据库访问.异常处理.消息队列.缓存服务.OSS服务,以及接口日志配置,接口文档生成等.如果每个项目都来一套,则既费力又难以维护.可以通过Spr ...

  8. 用Spring Boot零配置快速创建web项目(1)

    一.Spring Boot简介 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人 ...

  9. Spring boot入门(一):快速搭建Spring boot项目

    (一)Spring boot介绍 本部分摘自:https://www.zhihu.com/question/64671972/answer/223383505 Spring Boot是由Pivotal ...

  10. 《Spring Boot 入门及前后端分离项目实践》目录

    开篇词:SpringBoot入门及前后端分离项目实践导读 第02课:快速认识 Spring Boot 技术栈 第03课:开发环境搭建 第04课:快速构建 Spring Boot 应用 第05课:Spr ...

随机推荐

  1. Matplotlib.pyplot.scatter 散点图绘制

    Matplotlib.pyplot.plot 绘图 matplotlib.pyplot.scatter(x, y, s=None, c=None, marker=None, cmap=None, no ...

  2. Nginx的日志处理

    Nginx的日志处理 背景 之前一直被各种咨询nginx的使用问题. 大部分都是性能, 加模块, 以及一些tcp端口等的问题. 其实这些都还好, 还有一个比较麻烦的问题时日志相关的. nginx的日志 ...

  3. [转帖]WinXP添加TLS1.1、TLS1.2支持

    现象 HTTPS服务在Win7及Win10能够正常打开,但是在XP下用IE浏览器却无法打开,XP下用第三方浏览器(我试了谷歌浏览器)却能正常打开.经过抓包分析,用IE浏览器是协商用的是TLS1而用第三 ...

  4. [转帖]Debian开启SSH

    一.Debian开启SSH 参考链接: https://blog.csdn.net/zzpzheng/article/details/71170572 https://help.aliyun.com/ ...

  5. [转帖]clickhouse存储机制以及底层数据目录分布

    https://www.cnblogs.com/MrYang-11-GetKnow/p/15818141.html#:~:text=%E6%AF%8F%E4%B8%80%E4%B8%AA%E6%95% ...

  6. [转帖]一个小操作,SQL 查询速度翻了 1000 倍

    https://tidb.net/book/tidb-monthly/2022/2022-04/usercase/sql-1000 背景介绍​ 某一天早上来到公司,接到业务同学反馈,线上某个SQL之前 ...

  7. [转帖]Redis中的Lua脚本

    最近琢磨分布式锁时接触到的知识点,简单记一下. 文章目录 1. Redis中的Lua 2. 利用Lua操作Redis 3. Lua脚本的原子性 4. 关于 EVALSHA 5. 常用`SCRIPT` ...

  8. [转帖]Nginx性能优化详解

    https://developer.aliyun.com/article/886146?spm=a2c6h.24874632.expert-profile.256.7c46cfe9h5DxWK 感觉文 ...

  9. node中的fs模块和http模块的学习

    读取文件 fs 模块 第1个参数就是要读取的文件路径 第2个参数是一个回调函数(error,data)=>{} error 如果读取失败,error 就是错误对象 如果读取成功,error 就是 ...

  10. 你对iframe知道多少

    iframe 嵌套第三方页面出现的问题 我们需要通过一个接口获取被嵌套的地址. 然后将改地址赋值给iframe的src中,代码如下 <template> <div> <i ...