java复学 —— 一步步走

spring boot 2.6.0 mybatis-plus 3.5.9 swagger-ui 3.0.0 openapi-ui 1.8.0 ``

idea 创建一个 maven webapp 空项目,手动配置 spring mvc

教程

<dependencies>
<!--springMVC坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!--servlet坐标-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--jsp坐标-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
</dependencies>

配置 spring boot

<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.5.0</version>
</parent>
<dependencies>
<!-- Spring MVC依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springBoot的Test依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
</plugin>
</plugins>
</build>

配置 myBatis

教程
教程

手动配置 swagger3 docs

教程
教程
访问swagger界面报错汇总

配置 切面AOP,获取每次api调用的类和参数

@Aspect
@Component
public class ApiLoggingAspect {
private static final Logger logger = LoggerFactory.getLogger(ApiLoggingAspect.class);
// 定义切入点,匹配所有 controller 包下的方法
@Pointcut("execution(* com.booksSystem.controller..*(..))")
public void controllerMethods() {
}
// 在方法执行之前记录参数信息
@Before("controllerMethods()")
public void logMethodParameters(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getName();
Object[] args = joinPoint.getArgs();
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String httpMethod = request.getMethod();
String className = signature.getDeclaringTypeName();
logger.info("Request: {} - {}: {} - Params: {}", httpMethod,className,methodName,Arrays.toString(args));
}
// 在方法成功返回之后记录类名和方法名
@AfterReturning("controllerMethods()")
public void logClassNameAndMethodName(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
logger.info("Request Success");
}
}

mysql 创建数据库,创建数据表

CREATE DATABASE library_system
CHARACTER SET utf8
COLLATE utf8_general_ci;
-- ----------------------------
-- Table structure for books
-- ----------------------------
DROP TABLE IF EXISTS `books`;
CREATE TABLE `books` (
`id` bigint(0) NOT NULL AUTO_INCREMENT,
`book_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图书名称',
`book_price` decimal(10, 2) NULL DEFAULT NULL COMMENT '图书价格',
`is_delete` int(0) NULL DEFAULT NULL COMMENT '软删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

配置 mybatis-plus 软删除

mybatis-plus:
global-config:
db-config:
logic-delete-value: 1
logic-not-delete-value: 0
@TableLogic
private Integer deleted;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加逻辑删除插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}

mysql 练习

基本的语句

where、order by asc|desc、like、limit、group by、union、is null、is not null、

sql函数

round、avg、sum等

mybatis-plus 3.5.6 下配置 swagger-ui 3x 风格代码生成

CodeGenerator.java

package com.booksSystem.codeGenerator;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.sql.Types;
import java.util.Collections;
/**
* @Author lambert
* @Date 2024/12/23 18:45
* @Description: TODO
* @Version 1.0
*/
public class CodeGenerator {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/l_test?useUnicode=true&characterEncoding=utf-8", "root", "lamberts")
.globalConfig(builder -> {
builder.author("lambert") // 设置作者
.enableSwagger() // 开启 swagger 模式
.outputDir("/Users/lantian/Documents/code/java/library_system/code/"); // 指定输出目录
})
.dataSourceConfig(builder ->
builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
// 自定义类型转换
return DbColumnType.INTEGER;
}
return typeRegistry.getColumnType(metaInfo);
})
)
.packageConfig(builder ->
builder.parent("com.booksSystem") // 设置父包名
.moduleName("") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.xml, "/Users/lantian/Documents/code/java/library_system/code/xml/")) // 设置mapperXml生成路径
)
.strategyConfig(builder ->
builder
.addInclude("approval_departmental") // 设置需要生成的表名
.addTablePrefix("") // 设置过滤表前缀
.entityBuilder().enableFileOverride().enableLombok().enableTableFieldAnnotation()
.javaTemplate("/templates/entity.java")
.serviceBuilder().enableFileOverride()
.serviceTemplate("templates/service.java")
.serviceImplTemplate("templates/serviceImpl.java")
.mapperBuilder().enableFileOverride()
.mapperTemplate("templates/mapper.java").enableMapperAnnotation()
.controllerBuilder().enableFileOverride().enableRestStyle()
.build()
)
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}

MybatisPlusConfig.java

package com.booksSystem.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
/**
* @Author lambert
* @Date 2024/12/19 15:59
* @Description: TODO
* @Version 1.0
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加逻辑删除插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}

SwaggerUiConfig.java

package com.booksSystem.config;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Contact;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.info.License;
import io.swagger.v3.oas.annotations.servers.Server;
import org.springframework.boot.SpringBootConfiguration;
/**
* @author Anhui OuYang
* @version 1.0
**/
@SpringBootConfiguration
@OpenAPIDefinition(
// ## API的基本信息,包括标题、版本号、描述、联系人等
info = @Info(
title = "Swagger3.0 (Open API) 框架学习示例文档", // Api接口文档标题(必填)
description = "学习Swagger框架而用来定义测试的文档", // Api接口文档描述
version = "1.2.1", // Api接口版本
termsOfService = "https://example.com/", // Api接口的服务条款地址
contact = @Contact(
name = "lambert", // 作者名称
email = "***@163.com", // 作者邮箱
url = "https://www.cnblogs.com/lambertlt/" // 介绍作者的URL地址
),
license = @License( // 设置联系人信息
name = "Apache 2.0", // 授权名称
url = "https://www.apache.org/licenses/LICENSE-2.0.html" // 授权信息
)
),
// ## 表示服务器地址或者URL模板列表,多个服务地址随时切换(只不过是有多台IP有当前的服务API)
servers = {
@Server(url = "http://localhost:8080/", description = "本地测试服务器"),
// @Server(url = "http://192.168.2.236/demo/", description = "本地服务器二服务"),
},
externalDocs = @ExternalDocumentation(description = "更多内容请查看该链接", url = "xxx"))
public class SwaggerUiConfig {
}

WebMvcConfig.java

package com.booksSystem.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/").resourceChain(false);
registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}

controller.java.ftl

package ${package.Controller};
import org.springframework.web.bind.annotation.RequestMapping;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
<#if restControllerStyle>
import org.springframework.web.bind.annotation.RestController;
<#else>
import org.springframework.stereotype.Controller;
</#if>
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>
/**
* ${table.comment!} 前端控制器
*
* @author ${author}
* @since ${date}
*/
<#if restControllerStyle>
@RestController
<#else>
@Controller
</#if>
@Tag( name = "${table.controllerName}", description = "${table.comment}")
@RequestMapping("<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle>${controllerMappingHyphen}<#else>${table.entityPath}</#if>")
<#if kotlin>
class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if>
<#else>
<#if superControllerClass??>
public class ${table.controllerName} extends ${superControllerClass} {
<#else>
public class ${table.controllerName} {
</#if>
@Autowired
private ${table.serviceName} ${table.serviceName ? substring(1) ? uncap_first};
@GetMapping(value = "")
public ResponseEntity<List> all() {
List<${entity}> list = ${table.serviceName ? substring(1) ? uncap_first}.list();
return new ResponseEntity<>(list, HttpStatus.OK);
}
}
</#if>

service.java.ftl

package ${package.Service};
import ${package.Entity}.${entity};
import ${superServiceClassPackage};
/**
* ${table.comment!} 服务接口定义
*
* @author ${author}
* @since ${date}
*/
<#if kotlin>
interface ${table.serviceName} : ${superServiceClass}<${entity}>
<#else>
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {
}
</#if>

serviceImpl.java.ftl

package ${package.ServiceImpl};
import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
<#if generateService>
import ${package.Service}.${table.serviceName};
</#if>
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;
/**
* ${table.comment!} 服务接口实现类
* @author ${author}
* @since ${date}
*/
@Service
<#if kotlin>
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>()<#if generateService>, ${table.serviceName}</#if> {
}
<#else>
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}><#if generateService> implements ${table.serviceName}</#if> {
@Autowired
${entity}Mapper ${entity ? uncap_first}Mapper;
}
</#if>

entity.java.ftl

package ${package.Entity};
<#list table.importPackages as pkg>
import ${pkg};
</#list>
<#if springdoc>
import io.swagger.v3.oas.annotations.media.Schema;
<#elseif swagger>
import io.swagger.v3.oas.annotations.media.Schema;
</#if>
<#if entityLombokModel>
import lombok.Data;
<#if chainModel>
import lombok.experimental.Accessors;
</#if>
import java.util.Date;
</#if>
/**
* ${table.comment!}
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Data
<#if chainModel>
@Accessors(chain = true)
</#if>
</#if>
<#if table.convert>
@TableName("${schemaName}${table.name}")
</#if>
<#if springdoc>
@Schema(name = "${entity}", description = "${table.comment!}")
<#elseif swagger>
@Schema( name = "${entity}对象 - ${table.comment!}")
</#if>
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> {
<#elseif activeRecord>
public class ${entity} extends Model<${entity}> {
<#elseif entitySerialVersionUID>
public class ${entity} implements Serializable {
<#else>
public class ${entity} {
</#if>
<#if entitySerialVersionUID>
private static final long serialVersionUID = 1L;
</#if>
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field>
<#if field.keyFlag>
<#assign keyPropertyName="${field.propertyName}"/>
</#if>
<#if field.comment!?length gt 0>
<#if springdoc>
@Schema(description = "${field.comment}")
<#elseif swagger>
@Schema( name = "${field.comment}" )
<#else>
/**
* ${field.comment}
*/
</#if>
</#if>
<#if field.keyFlag>
<#-- 主键 -->
<#if field.keyIdentityFlag>
@TableId(value = "${field.annotationColumnName}", type = IdType.AUTO)
<#elseif idType??>
@TableId(value = "${field.annotationColumnName}", type = IdType.${idType})
<#elseif field.convert>
<#-- @TableId("${field.annotationColumnName}")-->
@TableId(value = "${field.annotationColumnName}", type = IdType.AUTO)
</#if>
<#-- 普通字段 -->
<#elseif field.fill??>
<#-- ----- 存在字段填充设置 ----->
<#if field.convert>
@TableField(value = "${field.annotationColumnName}", fill = FieldFill.${field.fill})
<#else>
@TableField(fill = FieldFill.${field.fill})
</#if>
<#elseif field.convert>
@TableField("${field.annotationColumnName}")
</#if>
<#-- 乐观锁注解 -->
<#if field.versionField>
@Version
</#if>
<#-- 逻辑删除注解 -->
<#if field.logicDeleteField>
@TableLogic
</#if>
<#if field.propertyType=="LocalDateTime">
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date ${field.propertyName};
<#else>
private ${field.propertyType} ${field.propertyName};
</#if>
</#list>
<#------------ END 字段循环遍历 ---------->
<#if !entityLombokModel>
<#list table.fields as field>
<#if field.propertyType == "boolean">
<#assign getprefix="is"/>
<#else>
<#assign getprefix="get"/>
</#if>
public ${field.propertyType} ${getprefix}${field.capitalName}() {
return ${field.propertyName};
}
<#if chainModel>
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
<#else>
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
</#if>
this.${field.propertyName} = ${field.propertyName};
<#if chainModel>
return this;
</#if>
}
</#list>
</#if>
<#if entityColumnConstant>
<#list table.fields as field>
public static final String ${field.name?upper_case} = "${field.name}";
</#list>
</#if>
<#if activeRecord>
@Override
public Serializable pkVal() {
<#if keyPropertyName??>
return this.${keyPropertyName};
<#else>
return null;
</#if>
}
</#if>
<#if !entityLombokModel>
@Override
public String toString() {
return "${entity}{" +
<#list table.fields as field>
<#if field_index==0>
"${field.propertyName} = " + ${field.propertyName} +
<#else>
", ${field.propertyName} = " + ${field.propertyName} +
</#if>
</#list>
"}";
}
</#if>
}

mapper.java.ftl

package ${package.Mapper};
import ${package.Entity}.${entity};
import ${superMapperClassPackage};
<#if mapperAnnotationClass??>
import ${mapperAnnotationClass.name};
</#if>
/**
* ${table.comment!} Mapper 接口
*
* @author ${author}
* @since ${date}
*/
<#if mapperAnnotationClass??>
@${mapperAnnotationClass.simpleName}
</#if>
<#if kotlin>
interface ${table.mapperName} : ${superMapperClass}<${entity}>
<#else>
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {
}
</#if>

mapper.xml.java.ftl

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${package.Mapper}.${table.mapperName}">
<#if enableCache>
<!-- 开启二级缓存 -->
<cache type="${cacheClassName}"/>
</#if>
<#if baseResultMap>
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="${package.Entity}.${entity}">
<#list table.fields as field>
<#if field.keyFlag><#--生成主键排在第一位-->
<id column="${field.name}" property="${field.propertyName}" />
</#if>
</#list>
<#list table.commonFields as field><#--生成公共字段 -->
<result column="${field.name}" property="${field.propertyName}" />
</#list>
<#list table.fields as field>
<#if !field.keyFlag><#--生成普通字段 -->
<result column="${field.name}" property="${field.propertyName}" />
</#if>
</#list>
</resultMap>
</#if>
<#if baseColumnList>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
<#list table.commonFields as field>
${field.columnName},
</#list>
${table.fieldNames}
</sql>
</#if>
</mapper>
posted @   lambertlt  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示