当前位置: 首页 > news >正文

重庆网站模板建站公司建网站程序怎么办

重庆网站模板建站公司,建网站程序怎么办,安卓开发者平台,seo是什么职位缩写知识点查漏补缺 跟着犬小哈做项目实战时发现好多知识点都忘了#xff0c;还有一些小的知识点可能之前没学过#xff0c;记录下#xff01;顺带整理下开发流程。 完整项目学习见犬小哈实战专栏 SpringBoot后端工程骨架 搭建好的工程骨架中实现了很多基础功能#xff0c;…知识点查漏补缺 跟着犬小哈做项目实战时发现好多知识点都忘了还有一些小的知识点可能之前没学过记录下顺带整理下开发流程。 完整项目学习见犬小哈实战专栏 SpringBoot后端工程骨架 搭建好的工程骨架中实现了很多基础功能如日志配置、参数校验、自定义响应、全局异常管理、Knife4j、Jackson序列化配置等。熟悉这些功能组件可以再以后开发新的项目时作为模板显著提升开发效率 1、多模块项目 1.1 parent标签 parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.6.3/version!-- Maven 从仓库中查找父项目--relativePath//parentparent 标签用于指定当前项目的父项目这意味着当前项目会继承父项目的一些配置例如插件版本、依赖版本、构建设置等。 1.2 modules标签 !-- 子模块管理--modules!-- 入口模块--moduleweblog-web/module!-- 管理后台 --moduleweblog-module-admin/module!-- 通用模块 --moduleweblog-module-common/module/modulesmodules标签用来模块管理 1.3 properties标签 properties!-- 项目版本号--revision0.0.1-SNAPSHOT/revisionjava.version1.8/java.versionguava.version31.1-jre/guava.versioncommons-lang3.version3.12.0/commons-lang3.versionjackson.verson2.15.2/jackson.versonproject.build.sourceEncodingUTF-8/project.build.sourceEncodingproject.reporting.outputEncodingUTF-8/project.reporting.outputEncoding!-- Maven 相关 --maven.compiler.source${java.version}/maven.compiler.sourcemaven.compiler.target${java.version}/maven.compiler.target/propertiesproperties标签中可以定义项目中可重用的属性或变量 1.4 dependencyManagement标签 dependencyManagementdependenciesdependencygroupIdcom.bijing/groupIdartifactIdweblog-module-admin/artifactIdversion${revision}/version/dependency......dependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactIdversion${jackson.verson}/version/dependency/dependencies/dependencyManagement 统一依赖管理,只是声明依赖并不自动实现引入,只有在子项目中写了该依赖项并且没有指定具体版本才会从父项目中继承该项。 1.5 pluginManagement标签 build!-- 统一插件管理用于管理 Maven 插件的版本和配置 --pluginManagement!-- 插件列表包含了各个插件的配置 --plugins!-- 插件配置 --plugin!-- Spring Boot Maven 插件用于构建和打包 Spring Boot 项目 --groupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId!-- 插件的配置信息 --configuration!-- 配置选项用于定制插件的行为 --!-- 排除特定的依赖这里是排除 lombok --excludesexcludegroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/exclude/excludes/configuration/plugin/plugins/pluginManagement/build在父项目中声明插件的版本以确保子项目使用相同的插件版本。 2、开发环境和生产环境配置 application.yml默认的主配置文件用于存放通用配置信息 # 企业级项目开发中一般项目默认会激活 dev 环境 spring:profiles:#默认激活 dev 环境active: dev application-dev.yml针对开发环境的配置文件 application-prod.yml针对生产环境的配置文件 # 在生产环境中使用特定的日志配置 logging:config: classpath:logback-weblog.xml3、日志配置 在web模块的 pom.xml 中加入 spring-boot-starter-web 依赖时它会自动包含 Logback 相关依赖无需额外添加。日志功能一般放在common模块中还需要加入下面依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependency!-- Jackson工具类 --dependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactId/dependency3.1 logback日志 logback-weblog.xml配置文件如下更多见博文 ?xml version1.0 encodingUTF-8? configuration!-- JMX配置用于连接和管理JMX工具 --jmxConfigurator/!-- 引入Spring Boot默认日志配置 --include resourceorg/springframework/boot/logging/logback/defaults.xml /!-- 定义应用名称 --property scopecontext nameappName valueweblog /!-- 自定义日志输出路径以及日志名称前缀 --property nameLOG_FILE value../../logs/${appName}.%d{yyyy-MM-dd}/property nameFILE_LOG_PATTERN value%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n/!-- 按照每天生成日志文件的配置 --appender nameFILE classch.qos.logback.core.rolling.RollingFileAppenderrollingPolicy classch.qos.logback.core.rolling.TimeBasedRollingPolicy!-- 日志文件输出的文件名格式 --FileNamePattern${LOG_FILE}-%i.log/FileNamePattern!-- 日志文件保留天数 --MaxHistory30/MaxHistory!-- 日志文件最大的大小当达到这个大小后会触发滚动 --TimeBasedFileNamingAndTriggeringPolicy classch.qos.logback.core.rolling.SizeAndTimeBasedFNATPmaxFileSize10MB/maxFileSize/TimeBasedFileNamingAndTriggeringPolicy/rollingPolicy!-- 配置日志格式 --encoder classch.qos.logback.classic.encoder.PatternLayoutEncoderpattern${FILE_LOG_PATTERN}/pattern/encoder/appender!-- dev环境配置仅输出到控制台 --springProfile namedevinclude resourceorg/springframework/boot/logging/logback/console-appender.xml /root levelinfoappender-ref refCONSOLE //root/springProfile!-- prod环境配置仅输出到文件中 --springProfile nameprodinclude resourceorg/springframework/boot/logging/logback/console-appender.xml /root levelINFOappender-ref refFILE //root/springProfile/configuration 3.2 Spring Boot 自定义注解实现 API 请求日志切面 3.2.1 自定义注解 一般四个步骤 创建自定义注解 这是定义自己的注解可以在需要的地方标记并可能带有一些属性。 package com.bijing.weblog.common.aspect;import java.lang.annotation.*;/*** author 毕晶* date 2024/2/3 20:50*/Retention(RetentionPolicy.RUNTIME)//表示该注解在运行时保留因此可以通过反射机制在运行时获取注解信息 Target({ElementType.METHOD})//表示该注解仅能被应用在方法上。 Documented//表示该注解将包含在 Javadoc 中 public interface ApiOperationLog {/*** API功能描述* return*/String description() default ;} 创建切面类Aspect 这是定义切面逻辑的地方。切面是使用注解的方法执行前后执行的代码块。 package com.bijing.weblog.common.aspect;import com.bijing.weblog.common.utils.JsonUtil; import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.MDC; import org.springframework.stereotype.Component;import java.lang.reflect.Method; import java.util.Arrays; import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors;/*** author 毕晶* date 2024/2/3 21:02*/ Aspect Component Slf4j public class ApiOperationLogAspect {/*** 以自定义 ApiOperationLog 注解为切点凡是添加 ApiOperationLog 的方法都会执行环绕中的代码*/Pointcut(annotation(com.bijing.weblog.common.aspect.ApiOperationLog))public void apiOperationLog() {}/*** 环绕** param joinPoint* return* throws Throwable*/Around(apiOperationLog())public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {try {// 请求开始时间long startTime System.currentTimeMillis();// MDC:诊断上下文映射,开发人员可以在 诊断上下文 中放置一些信息,如用户身份信息,关键参数,操作描述,环境信息,异常信息等// 而后通过特定的 logback 组件去获取,或者MDC.get(key)MDC.put(traceId, UUID.randomUUID().toString());// 获取被请求的类和方法// joinPoint 包含了被拦截方法的信息允许在拦截器中获取和控制被拦截方法的执行/*Signature: 通过 getSignature() 方法可以获取连接点的签名即被拦截方法的方法签名。Args: 通过 getArgs() 方法可以获取方法的参数数组。Target Object: 通过 getTarget() 方法可以获取目标对象即被拦截的对象实例。This Object: 通过 getThis() 方法可以获取代理对象即当前执行的代理对象。*/String className joinPoint.getTarget().getClass().getSimpleName();String methodName joinPoint.getSignature().getName();// 请求入参Object[] args joinPoint.getArgs();// 入参转 JSON 字符串// map(toJsonStr()):将流中的每个参数对象转换为相应的 JSON 字符串// collect(Collectors.joining(, )):将流中的元素收集并连接成一个字符串其中每个元素之间用逗号 , 分隔。String argsJsonStr Arrays.stream(args).map(toJsonStr()).collect(Collectors.joining(, ));// 功能描述信息String description getApiOperationLogDescription(joinPoint);// 打印请求相关参数log.info( 请求开始: [{}], 入参: {}, 请求类: {}, 请求方法: {} ,description, argsJsonStr, className, methodName);// 执行切点方法,result放的是被拦截方法的返回值Object result joinPoint.proceed();// 执行耗时long executionTime System.currentTimeMillis() - startTime;// 打印出参等相关信息log.info( 请求结束: [{}], 耗时: {}ms, 出参: {} ,description, executionTime, JsonUtil.toJsonString(result));return result;} finally {MDC.clear();}}/*** 获取注解的描述信息** param joinPoint* return*/private String getApiOperationLogDescription(ProceedingJoinPoint joinPoint) {// 1. 从 ProceedingJoinPoint 获取 MethodSignature(方法签名信息)MethodSignature signature (MethodSignature) joinPoint.getSignature();// 2. 使用 MethodSignature 获取当前被注解的 MethodMethod method signature.getMethod();// 3. 从 Method 中提取 LogExecution 注解ApiOperationLog apiOperationLog method.getAnnotation(ApiOperationLog.class);// 4. 从 LogExecution 注解中获取 description 属性return apiOperationLog.description();}/*** 转 JSON 字符串** return*/private FunctionObject, String toJsonStr() {return JsonUtil::toJsonString;} } 在启动类 WeblogWebApplication 中手动添加包扫描 ComponentScan 在多模块项目中Spring Boot 默认的组件扫描可能不会扫描所有模块的包因此可能需要手动指定要扫描的包。 package com.bijing.weblog.web;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan;SpringBootApplication ComponentScan({com.bijing.weblog.*})// 多模块项目中必需手动指定扫描 com.bijing.weblog 包下面的所有类 public class WeblogWebApplication {public static void main(String[] args) {SpringApplication.run(WeblogWebApplication.class, args);}} 在使用注解的方法上添加注解 在需要应用切面逻辑的方法上添加自定义注解这样 AOP 将在这些方法上生效。 补充SpringBoot的AOP是默认开启的不需要加注解EnableAspectJAutoProxy 3.2.2 拾遗 元注解说明 Retention(RetentionPolicy.RUNTIME) 这个元注解用于指定注解的保留策略即注解在何时生效。RetentionPolicy.RUNTIME 表示该注解将在运行时保留这意味着它可以通过反射在运行时被访问和解析。 Target({ElementType.METHOD}) 这个元注解用于指定注解的目标元素即可以在哪些地方使用这个注解。ElementType.METHOD 表示该注解只能用于方法上。这意味着您只能在方法上使用这个特定的注解。 Documented 这个元注解用于指定被注解的元素是否会出现在生成的Java文档中。如果一个注解使用了 Documented那么在生成文档时被注解的元素及其注解信息会被包含在文档中。这可以帮助文档生成工具如 JavaDoc在生成文档时展示关于注解的信息。 aspectj 注解说明 在配置 AOP 切面之前我们需要了解下 aspectj 相关注解的作用 Aspect声明该类为一个切面类 Pointcut定义一个切点后面跟随一个表达式表达式可以定义为切某个注解也可以切某个 package 下的方法 切点定义好后就是围绕这个切点做文章了 Before: 在切点之前织入相关代码 After: 在切点之后织入相关代码; AfterReturning: 在切点返回内容后织入相关代码一般用于对返回值做些加工处理的场景 AfterThrowing: 用来处理当织入的代码抛出异常后的逻辑处理; Around: 环绕可以在切入点前后织入代码并且可以自由的控制何时执行切点 4、参数校验 Spring Boot提供了强大的参数校验功能它建立在Java Bean Validation规范JSR 380之上。 4.1 引入依赖 首先需要在 weblog-web 模块中的 pom.xml 文件添加参数校验依赖 !-- 参数校验依赖--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-validation/artifactId/dependency 4.2 实体类参数校验 package com.bijing.weblog.web.model;import lombok.Data;import javax.validation.constraints.*;/*** author 毕晶* date 2024/2/3 23:40*/ Data public class User {// 用户名NotBlank(message 用户名不能为空)private String username;// 性别NotNull(message 性别不能为空)private Integer sex;// 年龄NotNull(message 年龄不能为空)Min(value 18, message 年龄必须大于或等于 18)Max(value 120, message 年龄必须小于或等于120)private Integer age;//邮箱NotBlank(message 邮箱不能为空)Email(message 邮箱格式不正确)private String email; } 4.3 Controller 参数校验 每个字段的校验注解添加完成后还需要在 controller 层进行捕获并将错误信息返回。 package com.bijing.weblog.web.controller;import com.bijing.weblog.common.aspect.ApiOperationLog; import com.bijing.weblog.web.model.User; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController;import java.util.stream.Collectors;/*** author 毕晶* date 2024/2/3 23:40*/ RestController Slf4j public class TestController {PostMapping(/test)ApiOperationLog(description 测试接口)public ResponseEntityString test(RequestBody Validated User user, BindingResult bindingResult) {// 是否存在校验错误if (bindingResult.hasErrors()) {// 获取校验不通过字段的提示信息String errorMsg bindingResult.getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.joining(, ));return ResponseEntity.badRequest().body(errorMsg);}// 返参return ResponseEntity.ok(参数没有任何问题);}}ResponseEntity Spring Framework 提供的一个表示 HTTP 响应的类。它包装了响应的状态码、头部信息和响应体等信息。 Validated: 告诉 Spring 需要对 User 对象执行校验; BindingResult : 验证的结果对象其中包含所有验证错误信息 4.4 拾遗 1、以下是 JSR 380 中提供的主要验证注解及其描述 注解描述NotNull验证对象值不应为 null。AssertTrue验证布尔值是否为 true。AssertFalse验证布尔值是否为 false。Min(value)验证数字是否不小于指定的最小值。Max(value)验证数字是否不大于指定的最大值。DecimalMin(value)验证数字值可以是浮点数是否不小于指定的最小值。DecimalMax(value)验证数字值可以是浮点数是否不大于指定的最大值。Positive验证数字值是否为正数。PositiveOrZero验证数字值是否为正数或零。Negative验证数字值是否为负数。NegativeOrZero验证数字值是否为负数或零。Size(min, max)验证元素的大小是否在给定的最小值和最大值之间。Digits(integer, fraction)验证数字是否在指定的位数范围内。Past验证日期或时间是否在当前时间之前。PastOrPresent验证日期或时间是否在当前时间或之前。Future验证日期或时间是否在当前时间之后。FutureOrPresent验证日期或时间是否在当前时间或之后。Pattern(regexp)验证字符串是否与给定的正则表达式匹配。NotEmpty验证元素不为 null并且其大小/长度大于0。NotBlank验证字符串不为 null且至少包含一个非空白字符。Email验证字符串是否符合有效的电子邮件格式。 除了上述的标准注解JSR 380 也支持开发者定义和使用自己的自定义验证注解。此外这个规范还提供了一系列的APIs和工具用于执行验证和处理验证结果。大部分现代Java框架如 Spring 和 Jakarta EE都与 JSR 380 兼容并支持其验证功能。 2、以下是 ResponseEntity 的一些主要用法 方法描述ok()创建一个状态码为 200 OK 的 ResponseEntity 对象。ok(T body)创建一个状态码为 200 OK 的 ResponseEntity 对象并设置响应体。status(HttpStatus status)创建一个指定状态码的 ResponseEntity 对象。status(int status)创建一个指定状态码的 ResponseEntity 对象。headers(HttpHeaders headers)设置响应头部信息。header(String headerName, String... headerValues)添加指定名称和值的响应头。body(T body)设置响应体。created(URI location)创建一个状态码为 201 Created 的 ResponseEntity 对象并设置 Location 头部信息。noContent()创建一个状态码为 204 No Content 的 ResponseEntity 对象。 4.5 查漏补缺 以下是 BindingResult 的一些主要用法和特点 主要用法和特点描述获取验证错误信息通过 bindingResult.getFieldErrors() 方法可以获取所有验证失败的字段信息每个字段错误包含字段名、错误码和默认错误信息等。验证错误判断使用 bindingResult.hasErrors() 方法来判断是否存在验证错误。如果存在验证错误可以根据实际情况进行相应的处理。默认错误信息如果验证失败BindingResult 会默认将错误信息存储在 FieldError 中可以通过 getDefaultMessage() 方法获取默认的错误信息。全局错误除了字段级别的错误信息BindingResult 还可以包含全局错误信息。通过 bindingResult.getGlobalErrors() 获取。 5、自定义响应工具类 在开发 RESTful API 时为了保持响应结构的一致性公司内部一般都有标准化的响应格式。 5.1 设计响应模型 5.1.1接口执行成功返参格式 {success: true,data: null }5.1.2接口执行异常返参格式 {success: false,errorCode: 10000message: 用户名不能为空 }5.2创建响应参数工具类 可以在common模块的utils包中定义响应参数工具类 package com.bijing.weblog.common.utils;import lombok.Data;import java.io.Serializable;/*** author 毕晶* date 2024/2/5 23:51*/ Data public class ResponseT implements Serializable {// 是否成功默认为 trueprivate boolean success true;// 响应消息private String message;// 异常码private String errorCode;// 响应数据private T data;// 成功响应 public static T ResponseT success() {ResponseT response new Response();return response;}public static T ResponseT success(T data) {ResponseT response new Response();response.setData(data);return response;}// 失败响应 public static T ResponseT fail() {ResponseT response new Response();response.setSuccess(false);return response;}public static T ResponseT fail(String errorMessage) {ResponseT response new Response();response.setSuccess(false);response.setMessage(errorMessage);return response;}public static T ResponseT fail(String errorCode, String errorMessage) {ResponseT response new Response();response.setSuccess(false);response.setErrorCode(errorCode);response.setMessage(errorMessage);return response;}} 5.3 在控制器中使用 有了 Response 工具类再配合 Spring Boot 的 RestController 或者 ResponseBody 注解 就可以快速生成 JSON 格式的响应数据了。 PostMapping(/test)ApiOperationLog(description 测试接口)public Response test(RequestBody Validated User user, BindingResult bindingResult) {// 是否存在校验错误if (bindingResult.hasErrors()) {// 获取校验不通过字段的提示信息String errorMsg bindingResult.getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.joining(, ));return Response.fail(errorMsg);}// 返参return Response.success();}补充 在接口的返参中有很多 null 值的字段也返回了咋办 只需在 applicaiton.yml 文件中对 jackson 添加相关配置即可。 jackson:# 设置后台返参若字段值为 null, 则不返回default-property-inclusion: non_null# 设置日期字段格式date-format: yyyy-MM-dd HH:mm:ss 6、全局异常管理 除了系统异常很多时候我们还需要处理业务异常比较推荐的做法是将自定义业务异常整合到全局异常管理中使其更加统一且易于维护。 6.1 自定义一个基础异常接口 创建一个 BaseExceptionInterface 基础异常接口方便后面做拓展。 package com.bijing.weblog.common.exception;/*** author 毕晶* date 2024/2/6 15:04*/ public interface BaseExceptionInterface {String getErrorCode();String getErrorMessage(); } 6.2 自定义错误码枚举 package com.bijing.weblog.common.enums;import com.bijing.weblog.common.exception.BaseExceptionInterface; import lombok.AllArgsConstructor; import lombok.Getter;/*** author 毕晶* date 2024/2/6 15:05* description 自定义错误码枚举*/ Getter AllArgsConstructor public enum ResponseCodeEnum implements BaseExceptionInterface {// ----------- 通用异常状态码 -----------SYSTEM_ERROR(10000, 出错啦后台小哥正在努力修复中...),// ----------- 业务异常状态码 -----------PRODUCT_NOT_FOUND(20000, 该产品不存在测试使用),;// 异常码private final String errorCode;// 错误信息private final String errorMessage;} 6.3 自定义业务异常 package com.bijing.weblog.common.exception;import lombok.Getter; import lombok.Setter;/*** author 毕晶* date 2024/2/6 15:10* description 自定义业务异常*/ Setter Getter public class BizException extends RuntimeException {// 异常码private String errorCode;// 错误信息private String errorMessage;public BizException(BaseExceptionInterface baseExceptionInterface) {this.errorCode baseExceptionInterface.getErrorCode();this.errorMessage baseExceptionInterface.getErrorMessage();} } 补充为啥是继承RuntimeException类而不是去实现BaseExceptionInterface接口呢 从设计的角度去考虑BizException的本质是个运行时异常实现BaseExceptionInterface接口是一种功能行为的实现这一点在继承RuntimeException时可以自定义实现因此就没有必要去实现BaseExceptionInterface接口了。当然实现了BaseExceptionInterface接口代码上也没有啥影响。 6.4 参数校验异常 当捕获到MethodArgumentNotValidException异常后我们可以通过全局异常处理器来捕获该异常统一返回错误信息。 改造 GlobalExceptionHandler 类添加 handleMethodArgumentNotValidException() 方法 /*** 捕获参数校验异常* return*/ExceptionHandler({MethodArgumentNotValidException.class})ResponseBodypublic ResponseObject handleMethodArgumentNotValidException(HttpServletRequest request,MethodArgumentNotValidException e) {// 参数错误异常码String errorCode ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode();// 获取 BindingResultBindingResult bindingResult e.getBindingResult();StringBuilder sb new StringBuilder();// 获取校验不通过的字段并组合错误信息格式为 email 邮箱格式不正确, 当前值: 123124qq.com;Optional.ofNullable(bindingResult.getFieldErrors()).ifPresent(errors - {errors.forEach(error -sb.append(error.getField()).append( ).append(error.getDefaultMessage()).append(, 当前值: ).append(error.getRejectedValue()).append(; ));});// 错误信息String errorMessage sb.toString();log.warn({} request error, errorCode: {}, errorMessage: {}, request.getRequestURI(), errorCode, errorMessage);return Response.fail(errorCode, errorMessage);}在参数错误枚举中添加 PARAM_NOT_VALID(10001, 参数错误),补充在Controller中需要不加 BindingResult 参数才能直接捕获其他异常并返回参数校验的异常信息。 PostMapping(/test)ApiOperationLog(description 测试接口) // 如果希望在发生验证错误时返回相应的错误信息就需要加上 BindingResult 参数。 // 如果不需要处理验证错误或者希望直接捕获其他异常并返回通用的错误信息就可以不加 BindingResult 参数。public Response test(RequestBody Validated User user) {......}7、整合 Knife4j Knife4j 是一个为 Java 项目生成和管理 API 文档的工具。 7.1 整合 Knife4j 在父项目 weblog-springboot 中的 pom.xml 文件中添加 Knife4j 依赖版本号 !-- 版本号统一管理 --properties!-- 依赖包版本 --省略... knife4j.version4.3.0/knife4j.version/properties!-- 统一依赖管理 --dependencyManagementdependencies省略... !-- knife4jAPI 文档工具 --dependencygroupIdcom.github.xiaoymin/groupIdartifactIdknife4j-openapi2-spring-boot-starter/artifactIdversion${knife4j.version}/version/dependency/dependencies/dependencyManagement因为 admin 后台管理模块和博客前台模块都需要调试接口所以我们需要在 weblog-web 和 weblog-module-admin 两个模块中都需要引入该依赖 !-- knife4j --dependencygroupIdcom.github.xiaoymin/groupIdartifactIdknife4j-openapi2-spring-boot-starter/artifactId/dependency7.2 添加配置类 新建名为 Knife4jConfig 配置类 package com.bijing.weblog.web.config;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.builders.RequestHandlerSelectors; 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.EnableSwagger2WebMvc;/*** author 毕晶* date 2024/2/7 16:22*/ Configuration EnableSwagger2WebMvc public class Knife4jConfig {Bean(webApi)public Docket createApiDoc() {Docket docket new Docket(DocumentationType.SWAGGER_2).apiInfo(buildApiInfo())// 分组名称.groupName(Web 前台接口).select()// 这里指定 Controller 扫描包路径.apis(RequestHandlerSelectors.basePackage(com.bijing.weblog.web.controller)).paths(PathSelectors.any()).build();return docket;}/*** 构建 API 信息** return*/private ApiInfo buildApiInfo() {return new ApiInfoBuilder().title(Weblog 博客前台接口文档) // 标题.description(Weblog 是一款由 Spring Boot Vue 3.2 Vite 4.3 开发的前后端分离博客。) // 描述.termsOfServiceUrl(https://www.bilog.com/) // API 服务条款.contact(new Contact(bijing, https://www.blog.com, 1457808125qq.com)) // 联系人.version(1.0) // 版本号.build();} } 浏览器访问路径 http://localhost:8080/doc.html , 就可以看到 api 管理界面了 7.3 给 controller 添加 Swagger 相关注解 7.4 生产环境如何屏蔽 Knife4j 7.4.1 Spring Boot Profile 特性 Profile 是 Spring Boot 中的一项特性允许你在不同环境中使用不同的配置。 Profile 注解:可以在配置类上添加 Profile 注解来控制 Knife4j 是否生效 。只有当指定的 Profile 处于激活状态时该配置类才会被创建和被使用。 Configuration EnableSwagger2WebMvc//启用 Swagger2 Profile(dev)// 只在 dev 环境中开启 public class Knife4jConfig { ... }7.4.2 分组功能 weblog 项目接口分为前台和 Admin 后台所以除了在 weblog-web 模块中配置 Knife4j 外还需要在 web-module-admin 也配置一份并使用 Knife4j 分组功能将各自的接口隔离开来。 添加依赖、配置类和前面类似注意类名和 Bean 的名称不能和 weblog-web 中的一样否则会冲突。然后改写分组名称以及包扫描路径还有 API 相关信息。 package com.bijing.weblog.admin.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; 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.EnableSwagger2WebMvc;/*** author 毕晶* date 2024/2/20 13:42*/ Configuration EnableSwagger2WebMvc Profile(dev) public class Knife4jAdminConfig {Bean(adminApi)public Docket createApiDoc() {Docket docket new Docket(DocumentationType.SWAGGER_2).apiInfo(buildApiInfo())// 分组名称.groupName(Admin 后台接口).select()// 这里指定 Controller 扫描包路径.apis(RequestHandlerSelectors.basePackage(com.bijing.weblog.admin.controller)).paths(PathSelectors.any()).build();return docket;}/*** 构建 API 信息** return*/private ApiInfo buildApiInfo() {return new ApiInfoBuilder().title(Weblog 博客前台接口文档) // 标题.description(Weblog 是一款由 Spring Boot Vue 3.2 Vite 4.3 开发的前后端分离博客。) // 描述.termsOfServiceUrl(https://www.bilog.com/) // API 服务条款.contact(new Contact(bijing, https://www.blog.com, 1457808125qq.com)) // 联系人.version(1.0) // 版本号.build();} } 7.5 拾遗 常用的Swagger相关注解以及它们的作用 注解作用Api描述整个API的信息包括标题、描述等。ApiOperation描述单个接口的信息包括接口的标题、描述、请求方法等。ApiParam描述接口的参数信息包括参数名、描述、是否必需等。ApiModel描述请求或响应的模型信息包括模型的名称、描述等。ApiModelProperty描述模型的属性信息包括属性的名称、描述、是否必需等。ApiIgnore用于忽略某个接口或模型不会被Swagger文档化。ApiImplicitParam描述接口的隐式参数信息一般用于描述请求头信息。ApiImplicitParams描述接口的多个隐式参数信息。ApiResponses描述接口的响应信息包括不同响应状态码对应的描述。ApiModelProperly描述模型的属性信息。 8、自定义 Jackson 序列化、反序列化支持 Java 8 日期新特性 8.1 自定义 Jackson 配置类 由于 Spring Boot 内置使用的就是 Jackson JSON 框架所以无需引入新的依赖仅需添加自定义配置类即可让其支持新的日期 API。 package com.bijing.weblog.common.config;import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.TimeZone;/*** author 毕晶* date 2024/2/20 13:58*/ Configuration public class JacksonConfig {Beanpublic ObjectMapper objectMapper() {// 初始化一个 ObjectMapper 对象用于自定义 Jackson 的行为ObjectMapper objectMapper new ObjectMapper();// 忽略未知字段前端有传入某个字段但是后端未定义接受该字段值则一律忽略掉objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);// JavaTimeModule 用于指定序列化和反序列化规则JavaTimeModule javaTimeModule new JavaTimeModule();// 支持 LocalDateTime、LocalDate、LocalTime的序列化和反序列化//定义LocalDateTime的序列化器javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss)));//定义LocalDateTime的反序列化器javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss)));javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(yyyy-MM-dd)));javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(yyyy -MM-dd)));javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(HH:mm:ss)));javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(HH:mm :ss)));objectMapper.registerModule(javaTimeModule);// 设置时区objectMapper.setTimeZone(TimeZone.getTimeZone(Asia/Shanghai));// 设置凡是为 null 的字段返参中均不返回请根据项目组约定是否开启// objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);return objectMapper;} } 完成自定义 Jackson 配置类后可以在原先的weblog-web模块下application.yml中删去jackson的一些无用配置。 8.2 拾遗 在Java 8中LocalDate、LocalTime 和 LocalDateTime 是处理日期和时间的重要类。 LocalDate LocalDate用于表示日期不包含时间部分。它只包含年、月、日三个字段。例如它可以用来表示员工的入职日期、某个活动的日期等。LocalDate对象通常用于需要日期信息但不涉及时间的场景。 LocalTime LocalTime用于表示时间不包含日期部分。它只包含时、分、秒三个字段可以包含纳秒精度。例如它可以用来表示公交车的首发时间、会议的开始时间等。LocalTime对象适用于那些只需要时间信息而日期信息不重要的场景。 LocalDateTime LocalDateTime是LocalDate和LocalTime的组合它同时包含日期和时间。它包含年、月、日、时、分、秒六个字段也可以包含纳秒精度。LocalDateTime对象适用于需要同时记录日期和时间的场景如在电商系统中记录交易发生的时间。 常用方法 方法描述LocalDate.now()获取当前日期LocalDate.of(int year, int month, int dayOfMonth)创建特定日期LocalTime.now()获取当前时间LocalTime.of(int hour, int minute)、LocalTime.of(int hour, int minute, int second)创建特定时间LocalDateTime.now()获取当前日期时间LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute)、LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second)创建特定日期时间getYear()、getMonthValue()、getDayOfMonth()获取年、月、日getHour()、getMinute()、getSecond()获取时、分、秒plusDays(long daysToAdd)、minusDays(long daysToSubtract)添加/减去指定天数plusHours(long hoursToAdd)、minusHours(long hoursToSubtract)添加/减去指定小时数isEqual(LocalDate/LocalTime/LocalDateTime other)比较日期/时间/日期时间是否相等isBefore(LocalDate/LocalTime/LocalDateTime other)、isAfter(LocalDate/LocalTime/LocalDateTime other)比较日期/时间/日期时间的大小关系
http://www.dnsts.com.cn/news/133797.html

相关文章:

  • 加强网站的建设网站用哪些系统做的比较好用
  • 郑州网站建设知识分享忘记php网站后台密码
  • 住房和城市建设厅网站域名和网站关联
  • 在那个网站做直播好赚钱吗安徽网站建设的基本步骤
  • 免费建站工具桂林象鼻山景区简介
  • 汕头市住房和城乡建设局网站代刷网站搭建教程
  • 电子商务网站建设答辩记录怎么做图片网站
  • 股票场外期权网站开发wordpress 地图导航代码
  • 建设中小企业网站山东网站备案公司吗
  • 网站文字优化方案黑龙江省公共资源
  • 旅游网站平台网站建设意义必要性
  • 做网站建设的怎么寻找客户太原最新情况
  • 建设银行信用卡网站登录wordpress 下载别人的主题
  • 网站建设和运维网站配色主题
  • 文化网站模版郑州小程序制作流程及费用
  • 国外网站建设视频教学漳州 外贸网站建设 SEO
  • 专业建站提供商开发者模式影响手机吗
  • 手机如何创造网站简易做海报网站
  • 西安建设门户网站企业地址管理系统
  • 中国黄冈网网站主机的选择与优化
  • 灵川建设局网站5944免费空间上搭建网站
  • wordpress建多个网站网站首页怎么做营业执照链接
  • 企业网站和官网的区别宜宾长宁网站建设
  • 企业站seo外包修改wordpress主题
  • 网站开发_运行及维护通辽做网站制作
  • 上海企业建设网站云南建设厅网站监理员培训
  • 北京网站维护公司宁波慈溪网站建设
  • 想要接网站业务如何做网页制作基础教程课件
  • 网站建设构架河南网站优化要多少钱
  • 母婴网站的功能设计网站备案文件