一、搭建数据库
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0 ;
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;
SET FOREIGN_KEY_CHECKS = 1 ;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0 ;
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;
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 {
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 {
@ApiModelProperty ( value= "是否成功" )
private Boolean success;
@ApiModelProperty ( value= "状态码" )
private Integer code;
@ApiModelProperty ( value= "返回消息" )
private String message;
@ApiModelProperty ( value= "返回数据" )
private Map < String , Object > data= new HashMap < > ( ) ;
private Result ( ) { }
private static Result result= new Result ( ) ;
public static Result ok ( ) {
result. setSuccess ( true ) ;
result. setCode ( ResultCode . SUCCESS) ;
result. setMessage ( "成功" ) ;
return result;
}
public static Result error ( ) {
result. setSuccess ( 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 ( ) ;
this . data. put ( key, value) ;
return this ;
}
public Result data ( Map < String , Object > map) {
this . setData ( map) ;
return this ;
}
}
4、整合swagger2
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
public class SwaggerConfig {
@Bean
public Docket webApiConfig ( ) {
List < Parameter > pars = new ArrayList < Parameter > ( ) ;
return new Docket ( DocumentationType . SWAGGER_2)
. groupName ( "webApi" )
. apiInfo ( webApiInfo ( ) )
. select ( )
. paths ( Predicates . not ( PathSelectors . regex ( "/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 ;
public class CodeGenerator {
@Test
public void run ( ) {
AutoGenerator mpg = new AutoGenerator ( ) ;
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" ) ;
gc. setIdType ( IdType . ID_WORKER_STR) ;
gc. setDateType ( DateType . ONLY_DATE) ;
gc. setSwagger2 ( true ) ;
mpg. setGlobalConfig ( gc) ;
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) ;
PackageConfig pc = new PackageConfig ( ) ;
pc. setParent ( "com.yzpnb" ) ;
pc. setModuleName ( "service_blog" ) ;
pc. setController ( "controller" ) ;
pc. setEntity ( "entity" ) ;
pc. setService ( "service" ) ;
pc. setMapper ( "mapper" ) ;
mpg. setPackageInfo ( pc) ;
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 ) ;
strategy. setRestControllerStyle ( true ) ;
strategy. setControllerMappingHyphenStyle ( true ) ;
mpg. setStrategy ( strategy) ;
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
spring :
application :
name : service- blog
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 :
date-format : yyyy- MM- DD HH: mm: ss
time-zone : GMT+8
mybatis-plus :
mapper-locations : classpath: com/yzpnb/service_blog/mapper/xml/*.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 ( ) ;
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
public class MyMpMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill ( MetaObject metaObject) {
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、全局异常
package com. yzpnb. service_base. handler ;
import lombok. AllArgsConstructor ;
import lombok. Data ;
import lombok. NoArgsConstructor ;
@Data
@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 ( ) ) ;
}
}
@GetMapping ( "selectAll" )
public Result selectAll ( ) {
List < MUser > list = mUserService. list ( ) ;
if ( true ) {
throw new CustomExceptionHandler ( 20000 , "自定义异常" ) ;
}
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 ( "*" ) ;
}
}