一:集成Swagger2:
首先在pom中添加依赖,然后通过编写配置类,最后可以通过@Conditional注解来选择生成API的时机,配置完成后通过
1-1:pom.xml
<!-- Swagger2.x -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.2.2</version>
</dependency>
1-2: SwaggerCondition.java
package com.redreamer.config.swagger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
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.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
@Conditional(SwaggerCondition.class)
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.redreamer.web"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使用Swagger2生成在线API")
.description("https://www.hh-medic.com/")
.termsOfServiceUrl("https://www.hh-medic.com/")
.contact("和缓医疗")
.version("v1.0")
.build();
}
}
1-3: 自定义Condition:SwaggerCondition.java
package com.redreamer.config.swagger; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; import java.util.Arrays; public class SwaggerCondition implements Condition { /** * 只在开发环境时swagger生效 * * @param conditionContext * @param annotatedTypeMetadata * @return */ @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { String[] activeProfiles = conditionContext.getEnvironment().getActiveProfiles(); return activeProfiles != null && Arrays.asList(activeProfiles).contains("dev"); } }
二:统一异常处理以及404处理
首先使用@ControllerAdvice来拦截状态不是404的异常,因为404比较特殊需要特殊配置一下
2-1:使用@ControllerAdvice来拦截状态不是404的异常
GlobalExceptionHandler.java
package com.redreamer.common.exception;
import com.redreamer.common.ResponseResult;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
/**
* 统一异常处理(404在ErrorController中处理)
*/
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ResponseResult<String> handleError(HttpServletRequest request, Exception e) {
int status = 400;
if (e instanceof ServiceException) {
status = ((ServiceException) e).getCode();
}
String requestURI = request.getRequestURI();
return new ResponseResult<>(status, e.getMessage(), requestURI);
}
}
2-2: 404异常处理
2-2-1:在Application.java添加如下配置(这里使用了Java 8 Lambda 表达式)
@Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return container -> { container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404")); }; }
2-2-2: 配置具体处理的类
NotFountExceptionHandler.java
package com.redreamer.common.exception; import com.redreamer.common.ResponseResult; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; @Controller public class NotFountExceptionHandler { /** * 需要在Application中配置如下: * * @param request * @return * @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { * return container -> { * container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404")); * }; * } */ @RequestMapping(value = "/404") @ResponseBody public ResponseResult<String> _404(HttpServletRequest request) { String realRequestPath = request.getAttribute("javax.servlet.forward.servlet_path").toString(); return new ResponseResult<>(404, "not fount", realRequestPath); } }
其他用的的类:
ResponseResult.java
package com.redreamer.common; import lombok.Data; import java.io.Serializable; /** * 统一返回结果处理 */ @Data public class ResponseResult<T> implements Serializable { private int status; // 状态 private String message; // 返回消息 private T data; // 具体数据 public ResponseResult() { this(200, "success"); } public ResponseResult(T data) { this(); this.data = data; } public ResponseResult(int status, String message) { this.status = status; this.message = message; } public ResponseResult(int status, String message, T data) { this.status = status; this.message = message; this.data = data; } // --------- 工厂方法创建返回结果 --------- public static <T> ResponseResult success(T data) { return new ResponseResult<>(data); } public static <T> ResponseResult success() { return new ResponseResult<>(); } }
ServiceException.java
package com.redreamer.common.exception; /** * 自定义异常 */ public class ServiceException extends RuntimeException { private int status; public ServiceException() { super(); } public ServiceException(String message) { super(message); } public ServiceException(Throwable cause) { super(cause); } public ServiceException(String message, Throwable cause) { super(message, cause); } public ServiceException(int status, String message) { super(message); this.status = status; } public ServiceException(int status, String message, Throwable cause) { super(message, cause); this.status = status; } public int getCode() { return status; } public void setCode(int status) { this.status = status; } }