spring boot+vue个人博客一:(后端)搭建spring boot脚手架
文章目录一、环境搭建1、数据库2、创建工程并引入依赖3、application.yaml4、启动类5、mybatis plus 分页插件6、代码生成器1、相关依赖2、配置(根据注释修改即可)3、编写controller并测试7、统一返回结果1、创建公共模块2、测试8、整合swagger测试接口一、环境搭建1、数据库CREATE TABLE `m_user` (`id` bigint(20) NOT
·
| 系列大纲 |
|---|
| GitHub(还没开发完成) |
| 暂时没有响应移动端,前、后端功能都只是随便写了点,因为最近有点事,等我处理完,会将功能开发完成,前端页面也会写一套CSS模块化+VUE组件化的组件库来构建 |
| 在线演示www.yzpnb.top |
| 第一章:(后端)搭建spring boot脚手架:https://blog.csdn.net/grd_java/article/details/107452826 |
| 第二章:权限整合shiro+jwt,完成后端接口:https://blog.csdn.net/grd_java/article/details/107481570 |
| 第三章:搭建前端vue整合element ui脚手架:https://blog.csdn.net/grd_java/article/details/107498140 |
| 第四章:首页和公共头部组件:https://blog.csdn.net/grd_java/article/details/107507213 |
| 第五章:完成登陆注册页面,nginx网关对接后端:https://blog.csdn.net/grd_java/article/details/107515437 |
| 第六章:博客页面,观看博客,博客编辑功能:https://blog.csdn.net/grd_java/article/details/107525128 |
| 第七章:打包部署,多节点部署方案:https://blog.csdn.net/grd_java/article/details/107533253 |
文章目录
一、搭建数据库
/*
Navicat Premium Data Transfer
Source Server : localhost_3306
Source Server Type : MySQL
Source Server Version : 80017
Source Host : localhost:3306
Source Schema : myblog
Target Server Type : MySQL
Target Server Version : 80017
File Encoding : 65001
Date: 20/07/2020 17:32:56
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for m_blog
-- ----------------------------
DROP TABLE IF EXISTS `m_blog`;
CREATE TABLE `m_blog` (
`id` char(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '博客id',
`user_id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户id',
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '博客标题',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '简介内容',
`content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '内容',
`gmt_create` datetime(0) NOT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '创建时间',
`status` tinyint(4) NOT NULL COMMENT '发布状态',
`gmt_modified` datetime(0) NOT NULL COMMENT '修改时间',
`is_delete` tinyint(1) NOT NULL COMMENT '逻辑删除1删除,0未删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of m_blog
-- ----------------------------
SET FOREIGN_KEY_CHECKS = 1;
/*
Navicat Premium Data Transfer
Source Server : localhost_3306
Source Server Type : MySQL
Source Server Version : 80017
Source Host : localhost:3306
Source Schema : myblog
Target Server Type : MySQL
Target Server Version : 80017
File Encoding : 65001
Date: 20/07/2020 17:34:06
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for m_user
-- ----------------------------
DROP TABLE IF EXISTS `m_user`;
CREATE TABLE `m_user` (
`id` char(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户id',
`username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
`avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像',
`email` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
`password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码',
`status` int(5) NOT NULL COMMENT '状态',
`gmt_created` datetime(0) NOT NULL COMMENT '创建时间',
`gmt_modified` datetime(0) NOT NULL COMMENT '更新时间',
`is_delete` tinyint(1) NOT NULL COMMENT '逻辑删除1删除,0未删除',
PRIMARY KEY (`id`) USING BTREE,
INDEX `UK_USERNAME`(`username`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of m_user
-- ----------------------------
INSERT INTO `m_user` VALUES ('1', 'markerhub', 'https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg', NULL, '96e79218965eb72c92a549dd5a330112', 0, '2020-04-20 10:44:01', '0000-00-00 00:00:00', 0);
SET FOREIGN_KEY_CHECKS = 1;



| 记住每个表加两条数据 |
|---|
二、分布式环境搭建
1、创建父工程引入依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yzpnb</groupId>
<artifactId>myblog</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<!--spring boot 父依赖-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
</parent>
<!--依赖-->
<dependencies>
<!--spring boot test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--lombook-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
<!--管理依赖-->
<dependencyManagement>
<dependencies>
<!--spring cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR4</version>
<type>pom</type>
<scope>import</scope>
<!--注意这里使用<scope>import</scope>是为了预防jar包依赖引用
import只能用于<dependencyManagement>中并且设置<type>pom</type>的依赖中。
可以使子模块不使用父模块的引用jar包
如果不设置此项,就会报错(你可以注释掉试试),因为子模块在引用某些jar包时,会引用父模块中的jar包
从而jar包冲突-->
</dependency>
</dependencies>
</dependencyManagement>
</project>

2、创建子模块和全局模块,引入依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>myblog</artifactId>
<groupId>com.yzpnb</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common</artifactId>
<dependencies>
<!--mybatis plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<!--mybatis plus 代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.1</version>
</dependency>
<!--添加 模板引擎 依赖,MyBatis-Plus 支持 Velocity(默认):这是代码生成器需要的依赖-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
<!--代码生成器需要的依赖,swagger,处理ApiModel-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
</project>

<!--spring boot web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

3、定制统一返回接口
| 封装状态码 |
|---|

package com.yzpnb.common_utils;
public interface ResultCode {
/**
* 状态码
* 20000:代表成功
* 20001:代表错误
*/
public static Integer SUCCESS =20000;
public static Integer ERROR =20001;
}
| 统一返回结果 |
|---|

package com.yzpnb.common_utils;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
@Data
public class Result {
/**
* 当我们返回json字符串的时候,可以按以下规则
* {
* "sucess":布尔值, //表示是否响应成功
* "code":数字, //响应码
* "message":字符串, //返回信息
* "data":HashMap, //返回的数据
* }
*
* 创建成员变量
*/
@ApiModelProperty(value="是否成功")
private Boolean success;
@ApiModelProperty(value="状态码")
private Integer code;
@ApiModelProperty(value="返回消息")
private String message;
@ApiModelProperty(value="返回数据")
private Map<String,Object> data=new HashMap<>();
/**私有化构造方法:就是说除了Result类本身,其它类不能new Result类的对象了**/
private Result(){}
/**获取一个私有的Result对象。Result本身是可以new 对象,无论私有与否**/
private static Result result=new Result();
/**处理响应成功的静态方法**/
public static Result ok(){
result.setSuccess(true); //设置为true,表示处理响应成功
result.setCode(ResultCode.SUCCESS); //调用我们提供状态码的接口,设置状态码
result.setMessage("成功"); //设置提示信息
return result; //返回对象,外键不能new,只能通过静态方法获取对象
}
/**处理响应失败的静态方法**/
public static Result error(){
result.setSuccess(false); //设置为false,表示处理响应失败
result.setCode(ResultCode.ERROR); //调用我们提供状态码的接口,设置状态码
result.setMessage("失败"); //设置提示信息
return result;
}
/**设置值方法*/
public Result succes(Boolean b){
this.success=b;
return this;
}
public Result code(Integer i){
this.code=i;
return this;
}
public Result message(String str){
this.message=str;
return this;
}
public Result data(String key ,Object value){
this.data.clear();//先清空,因为我这里是单例设计模式,data中数据永远都在
this.data.put(key,value);
return this;
}
public Result data(Map<String , Object> map){
this.setData(map);
return this;
}
}
4、整合swagger2
| swagger 常用注解 |
|---|
| 创建公共配置模块配置 |
|---|


package com.yzpnb.service_base.config;
import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2//表中此类为Swagger2
public class SwaggerConfig {
@Bean
public Docket webApiConfig() {
List<Parameter> pars = new ArrayList<Parameter>();
return new Docket(DocumentationType.SWAGGER_2)
.groupName("webApi")//分组名
.apiInfo(webApiInfo())//在线文档的信息,传入ApiInfo对象,就是下面内个方法返回的对象
.select()
.paths(Predicates.not(PathSelectors.regex("/admin/.*")))//路径中包含admin时不显示信息
.paths(Predicates.not(PathSelectors.regex("/error/.*")))
.build();
}
private ApiInfo webApiInfo() {
return new ApiInfoBuilder()
.title("gulischool 接口 API 文档")
.description("展示先做基础功能,后面再添加业务")
.termsOfServiceUrl("https://www.yzpnb.com/aa/")
.version("1.0")
.contact(new Contact("Helen","http://yzpnb.com","915501928@qq.com"))
.build();
}
}
5、代码生成器


package com.yzpnb;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.Test;
/**
* @author
* @since 2018/12/13
*/
public class CodeGenerator {
@Test
public void run() {
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir("D:\\IdeaProjects\\myblog\\service\\service_blog" + "/src/main/java"); //输出目录,生成的代码最终输出的地方,请写你的项目的绝对路径
gc.setAuthor("testjava");
gc.setOpen(false); //生成后是否打开资源管理器
gc.setFileOverride(false); //重新生成时文件是否覆盖
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setIdType(IdType.ID_WORKER_STR); //主键策略,ID_WORKER表示默认Integer,ID_WORKER_STR表示字符型
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
gc.setSwagger2(true);//开启Swagger2模式
mpg.setGlobalConfig(gc);
// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/myblog?serverTimeZone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 4、包配置(生成的包名)
PackageConfig pc = new PackageConfig();
pc.setParent("com.yzpnb");
pc.setModuleName("service_blog"); //模块名 com.yzpnb.service_blog
pc.setController("controller"); //com.yzpnb.eduservice.controller
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("m_user","m_blog");//你要为哪个表生成代码
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
}

6、启动类
package com.yzpnb.service_blog;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan("com.yzpnb")
public class BlogApplication {
public static void main(String[] args) {
SpringApplication.run(BlogApplication.class,args);
}
}

7、整合MyBatis Plus
1、application.yaml
server:
port: 8001 #微服务端口号为8001
spring:
application:
name: service-blog #服务名
# profiles:
# active: dev #环境设置 dev表示构建阶段,test表示测试阶段,prod表示发布阶段
datasource: #数据源
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/myblog?serverTimeZone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123456
jackson: #我们的时区是东八区,应该加8个小时,时区显示格式也需要改成我们想要的
date-format: yyyy-MM-DD HH:mm:ss
time-zone: GMT+8
mybatis-plus:
mapper-locations: classpath:com/yzpnb/service_blog/mapper/xml/*.xml #配置mapper xml文件的路径

2、配置类
package com.yzpnb.service_base.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan(value="com.yzpnb.*.mapper")
public class MpConfiguration {
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
}

3、配置自动填充

package com.yzpnb.service_base.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component//将组件注入到IOC容器
public class MyMpMetaObjectHandler implements MetaObjectHandler{
@Override
public void insertFill(MetaObject metaObject) {
/**注意这里的监听字段gmtCreate和gmtModified是java属性名,不是字段名*/
this.setFieldValByName("gmtCreate",new Date(),metaObject);
this.setFieldValByName("gmtModified",new Date(),metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("gmtModified",new Date(),metaObject);
}
}
刚刚写完第二章,发现自动填充这里字段名写错了 this.setFieldValByName("gmtCreate",new Date(),metaObject); |
|---|
| 我在数据库中字段叫gmtCreated,所以如果你使用我的sql代码生成数据库表 |
| 请到数据库中将这个字段都修改为gmtCreate |
4、测试


8、全局异常
| 如果你需要处理全局异常,就需要web包 |
|---|

| 创建自定义异常 |
|---|
package com.yzpnb.service_base.handler;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 自定义异常类
* */
@Data//为类中成员变量自动生成get set toString
@AllArgsConstructor //自动生成有参构造方法,参数是所有参数
@NoArgsConstructor //自动生成无参构造
public class CustomExceptionHandler extends RuntimeException{
private Integer code;//状态码
private String message;//异常信息
}

| 创建通用异常,引用自定义异常 |
|---|
package com.yzpnb.service_base.handler;
import com.yzpnb.common_utils.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice//全局异常处理、全局数据绑定、全局数据预处理
public class MyExceptionHandler {
/**处理自定义异常*/
@ExceptionHandler(CustomExceptionHandler.class)//表示此方法只对我们自己定义的这个异常有效
@ResponseBody
public Result customError(CustomExceptionHandler e){//参数就是我们自定义异常类的对象
e.printStackTrace();//父类提供的方法
return Result.error().code(e.getCode()).message(e.getMessage());//将统一返回结果的状态码和提示信息,换为自定以异常的
}
}

| controller测试 |
|---|
@GetMapping("selectAll")
public Result selectAll(){
List<MUser> list = mUserService.list();
if(true){
throw new CustomExceptionHandler(20000,"自定义异常");//只要我们抛这个异常,那么MyExceptionHandler中的方法就会执行,因为设置了方法只监听这个异常
}
return Result.ok().data("all",list);
}


9、解决跨域问题

package com.yzpnb.service_base.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 解决跨域问题
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}
| 第二节:整合shiro+jwt,完成后端接口开发 |
|---|
| https://blog.csdn.net/grd_java/article/details/107481570 |
更多推荐




所有评论(0)