导航:

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. [转帖]从v8到v9,Arm服务器发展之路

    https://zhuanlan.zhihu.com/p/615344155   01 ARM:3A大作 将 CPU 的设计与制造相分离的代工模式,给 AMD 提供了高度的灵活性.第二.三代 EPYC ...

  2. Linux 通过命令方式反编译jar包的方法

    第一步: 复制jar包到指定路径. find . -iname "*.jar" -exec scp {} /root/bf/ \; 第二步: 解压缩jar包解压缩出来class文件 ...

  3. 手工创建一个带sticky模块的nginx镜像 并且实现容器化负载均衡的方法

    最近想进行容器化运行的nginx反向代理负载均衡服务. 找了一下 dockerhub上面的 nginx 发现里面不包含 sticky模块. 会报错为: nginx: [emerg] unknown d ...

  4. python批量上传文件到七牛云

    导航 引子 棘手的需求 化繁为简 实战案例 结语 参考 本文首发于智客工坊-<python批量上传文件到七牛云>,感谢您的阅读,预计阅读时长3min. 古之立大事者,不惟有超世之才,亦必有 ...

  5. Seata配置参考

    注意:mysql.redis等连接密码需修改为相应值 Seata-Server 环境 版本:1.4.2 OS: CentOS Linux release 7.5.1804 (Core) ip:192. ...

  6. elemetui-中在input框中回车

    在input框中回车 <el-input @keyup.enter.native="gotoLogin" class="my-el-input" plac ...

  7. 替换 &开头。;结尾之间的内容。用空格代替他们

    替换 &开头.;结尾之间的内容.用空格代替他们 var regExp = /\&.*?\;/g; var str = '123&asdsa;dqwe'; str = str.r ...

  8. Go中字符串处理:fmt.Sprintf与string.Builder的比较

    在Go语言中,我们通常会遇到两种主要的方式来处理和操作字符串:使用fmt.Sprintf函数和string.Builder类型.尽管两者都可以实现字符串的格式化和连接,但它们在性能和用法上有一些关键区 ...

  9. 简单的git拉取修改提交用法

    打开终端,进入要存放代码的本地文件夹,并使用git clone命令克隆远程仓库到本地: git clone https://github.com/username/repo.git 这里的userna ...

  10. 错误的daemon.json配置,导致docker容器启动失败 Failed to start Docker Application Container Engine

    docker学习-配置错误的源 问题点剖析 参考 docker学习-配置错误的源 问题点剖析 使用docker安装了nginx,编写Dockerfile,映射端口,终于跑起来了.但是,当我重启服务器, ...