配置文件加载到静态文件中去
private static String value;
@Value("${version}")
public void setValue(String version){
value = version;
}
实现Runable类无法使用自动注入
因为Java默认多线程不能自动注入
可以手动注入解决问题
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
/**
* 上下文对象实例
*/
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 获取applicationContext
*
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 通过name获取 Bean.
*
* @param name
* @return
*/
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
/**
* 通过class获取Bean.
*
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
/**
* 通过name,以及Clazz返回指定的Bean
*
* @param name
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
之后直接调用这个类的方法就可以了
private UserinfoService userinfoService;
public Running() {
this.userinfoService = ApplicationContextProvider.getBean(UserinfoService.class);
}
new方法中加入SpringBoot的自动注入方式
@Component
public class ServerConfig implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (ServerConfig.applicationContext ==null){
ServerConfig.applicationContext = applicationContext;
}
}
// 获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
// 通过name获取 Bean.
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
// 通过class获取Bean.
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
// 通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
在new的方法下
private static HookFromHandler hookFromHandler;
private static INettyLogService nettyLogService;
static {
hookFromHandler = ServerConfig.getBean(HookFromHandler.class);
nettyLogService = ServerConfig.getBean(INettyLogService.class);
}
LocalDate返回中有T,返回时间为空,对象接不到
//未测试
@Configuration
public class LocalDateTimeSerializerConfig {
//方法 一
@Bean
public LocalDateTimeSerializer localDateTimeDeserializer() {
return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer());
}
//方法 二
/* @Bean(name = "mapperObject")
public ObjectMapper getObjectMapper() {
ObjectMapper om = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
om.registerModule(javaTimeModule);
return om;
}*/
}
//已测
使用注解
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime positionTime;
跨域拦截器不生效
当自定义拦截器和跨域拦截器一起使用时,自定义拦截器的Order级别要比跨域拦截器的数字低,导致跨域拦截器不生效,应提高跨域拦截器的执行。
1. 提高Order
2. 将跨域定在过滤器中
异步失效情况
异步实际上使用的是代理做到的,SpringBoot会默认检测到注解,会建立一个代理类去继承备异步注解的方法,当调用时实际上使用的是代理类。
1.类必须是被@Component注解修饰
2. 类必须不能被@Configuration (未找到原因)
3. 不能使用在自身类中,自己掉自己不会走代理
4. 调用必须通过注入形式,不然SpringBoot的代理拿不到
Annotation that marks a method as a candidate for asynchronous execution. Can also be used at the type level, in which case all of the type's methods are considered as asynchronous. Note, however, that @Async is not supported on methods declared within a @Configuration class.
In terms of target method signatures, any parameter types are supported. However, the return type is constrained to either void or java.util.concurrent.Future. In the latter case, you may declare the more specific org.springframework.util.concurrent.ListenableFuture or java.util.concurrent.CompletableFuture types which allow for richer interaction with the asynchronous task and for immediate composition with further processing steps.
A Future handle returned from the proxy will be an actual asynchronous Future that can be used to track the result of the asynchronous method execution. However, since the target method needs to implement the same signature, it will have to return a temporary Future handle that just passes a value through: e.g. Spring's AsyncResult, EJB 3.1's javax.ejb.AsyncResult, or java.util.concurrent.CompletableFuture.completedFuture(Object).
Since:
3.0
See Also:
AnnotationAsyncExecutionInterceptor, AsyncAnnotationAdvisor
Author:
Juergen Hoeller, Chris Beams
继承OncePerRequestFilter自动注入不生效
属性上加入构造器
private RedisCacheUtils redisCacheUtils;
public PostFilter(RedisCacheUtils redisCacheUtils) {
this.redisCacheUtils = redisCacheUtils;
}
配置类中配置
@Configuration
public class WebConfig{
@Autowired
private RedisCacheUtils redisCacheUtils;
@Bean
public FilterRegistrationBean WebFilterDemo(){
//配置过滤器
FilterRegistrationBean frBean = new FilterRegistrationBean();
frBean.setFilter(new PostFilter(redisCacheUtils));
frBean.addUrlPatterns("/*");
frBean.setName("webFilterDemo");
//springBoot会按照order值的大小,从小到大的顺序来依次过滤。
// frBean.setOrder(0);
return frBean;
}
}
Swagger配置
配置类
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
@Configuration
@EnableSwagger2
@Slf4j
public class SwaggerConfig {
@Value("${custom.swaggerEnable}")
private Boolean enabled;
/*访问地址 http://localhost:8099/swagger-ui.html*/
@Bean
public Docket authApi() {
return new Docket(DocumentationType.SWAGGER_2)
.enable(enabled)
.apiInfo(apiInfo("描述 处罚单"))
.select()
// 扫描所有有注解的api,用这种方式更灵活
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
// 扫描指定包中的swagger注解
.apis(RequestHandlerSelectors.basePackage("com.penalty.controller"))
.build()
.groupName("处罚单")
.pathMapping("/")
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
}
@SuppressWarnings("deprecation")
private static Optional<? extends Class<?>> declaringClass(RequestHandler requestHandler) {
return Optional.ofNullable(requestHandler.declaringClass());
}
/**
* 校验基础包
*/
private static Function<Class<?>, Boolean> handlerPackage(final String basePackage) {
return input -> {
for (String strPackage : basePackage.split(";")) {
boolean isMatch = input.getPackage().getName().startsWith(strPackage);
if (isMatch) {
return true;
}
}
return false;
};
}
// ---------------------改写RequestHandlerSelectors中方法----------------------------
private List<SecurityScheme> securitySchemes() {
List<SecurityScheme> l = new ArrayList<>();
l.add(new ApiKey("authorization", "authorization", "header"));
l.add(new ApiKey("loginType", "loginType", "header"));
return l;
}
private List<SecurityContext> securityContexts() {
List<SecurityContext> l = new ArrayList<>();
l.add(SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("^(?!/demo|/auth).*$"))
.build());
return l;
}
List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
List<SecurityReference> l = new ArrayList<>();
l.add(new SecurityReference("authorization", authorizationScopes));
l.add(new SecurityReference("loginType", authorizationScopes));
return l;
}
/**
* api信息
*/
private ApiInfo apiInfo(String description) {
return new ApiInfoBuilder().title("处罚单管理").contact(new Contact("经纬智联开发部", null, null))
.description(description).version("1.0.0").build();
}
}
加入Web拦截
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 通用配置
*/
@Configuration
public class ResourcesConfig implements WebMvcConfigurer {
@Autowired
private RepeatSubmitInterceptor repeatSubmitInterceptor;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// swagger配置
registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
}
}
restFul配置
RESTFUL风格类上不能加@ApiModel
private T data;泛型不能加注解
必须要用泛型模式<T>,否则不显示
@Data
public class WebResponse<T> {
/**
* 0-成功;其他-失败 必填
*/
@ApiModelProperty(value = "0-成功;其他-失败 必填",name = "code",example = "200",required = true)
private int result;
/**
* 失败时的错误信息 非必填
*/
@ApiModelProperty(value = "失败时的错误信息 非必填",name = "error_msg")
private String error_msg;
/**
* 成功时的手机号信息,说明如下表 非必填
*/
private T data;
public WebResponse() {
this(0, null);
}
public WebResponse(int result, String resultMsg) {
this(result, resultMsg, null);
}
public WebResponse(T data) {
this(0, null, data);
}
public WebResponse(int result, String resultMsg, T data) {
this.result = result;
if (result != 0) {
this.error_msg = resultMsg;
}
this.data = data;
}
public static WebResponse error(BaseError baseError){
return new WebResponse(baseError.getErrorCode(), baseError.getErrMsg());
}
public static WebResponse success(){
return new WebResponse();
}
public static <T> WebResponse<T> success(T o){
return new WebResponse(o);
}
}