Halo(二)
@Conditional 满足条件给容器注册Bean(在配置类 @Configuration 的类和方法上配置)
需要实现Condition接口, 实现matches方法
public class LdCondition implements Condition{
@Override
public boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
//从这里获取配置文件中 active 的值,根据当前的 active 值决定是否加载类
String[] activeProfiles = environment.getActiveProfiles();
for (String active : activeProfiles) {
if(active.equals(ActiveEnum.open_active.getActive().toString())){
return true;
}
}
return false;
}
}
标注在类上:
一个类中可以注入很多实例,@Conditional标注在类上就决定了一批bean是否注入。
标记在方法上
@Configuration
public class BeanConfig {
//只有一个类时,大括号可以省略
//如果LdCondition的实现方法返回true,则注入这个bean
@Conditional({LdCondition.class})
@Bean("person")
public Person person(){
return new Person("ld",22);
}
}
@ConditionalOnMissingBean:
容器中没有就注入,有就不注入。
@ConditionalOnMissingBean:
容器中没有就不注入,有就注入。
FilterRegistrationBean 自定义过滤器(配置类 @Configuration 中)
使用FilterRegistrationBean来注册Filter:
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
FilterRegistrationBean<CorsFilter> corsFilter = new FilterRegistrationBean<>();
//设置优先级
corsFilter.setOrder(Ordered.HIGHEST_PRECEDENCE + 10);
//注册过滤器
corsFilter.setFilter(new CorsFilter());
//拦截路径
corsFilter.addUrlPatterns("/api/*");
return corsFilter;
}
SpringBoot 整合 Swagger2(配置类 @Configuration 上)
依赖:
implementation "io.springfox:springfox-swagger2:$swaggerVersion"
implementation "io.springfox:springfox-swagger-ui:$swaggerVersion"
一般 swagger 需要的权限(需要在对应的模块进行排除):
http://localhost:8080/swagger-resources/configuration/ui
http://localhost:8080/swagger-resources
http://localhost:8080/api-docs
http://localhost:8080/swagger-ui.html
http://localhost:8080/swagger-resources/configuration/security
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
@Api("评论接口"):
用在类上,说明该类的作用
@ApiOperation(value="获取评论", notes="根据id获取评论"):
用在方法上,说明方法的作用,标注在具体请求上。
value和notes的作用差不多,都是对请求进行说明;
tags则是对请求进行分类的,
比如你有好几个controller,分别属于不同的功能模块,那这里我们就可以使用tags来区分了。
@ApiImplicitParams:
用在方法上包含一组参数说明。
@ApiImplicitParam(name = "id", value = "12", required = true, dataType = "String"):
用在@ApiImplicitParams注解中,指定一个请求参数的各个方面。
@ApiResponses:
用于表示一组响应
@ApiResponse:
用在@ApiResponses中,一般用于表达一个错误的响应信息。
@ApiModel:
描述一个Model的信息
这种一般用在post创建的时候,使用@RequestBody这样的场景,请求参数无法使用@ApiImplicitParam注解进行描述时。
表明这是一个被swagger框架管理的model,用于class上。
@ApiModelProperty:
描述一个model的属性,就是标注在被标注了@ApiModel的class的属性上,
这里的value是对字段的描述,example是取值例子。
Swagger2配置:
@EnableSwagger2
@Configuration
public class SwaggerConfiguration {
@Bean
public Docket haloDefaultApi() {
return buildApiDocket("content",
"api.content",
"/api/content/**");
}
@Bean
public Docket haloAdminApi() {
return buildApiDocket("admin",
"api.admin",
"/api/admin/**");
}
private Docket buildApiDocket(@NonNull String groupName, @NonNull String basePackage, @NonNull String antPattern) {
Assert.hasText(groupName, "Group name must not be blank");
Assert.hasText(basePackage, "Base package must not be blank");
Assert.hasText(antPattern, "Ant pattern must not be blank");
return new Docket(DocumentationType.SWAGGER_2)
.groupName(groupName)
.select()
.apis(RequestHandlerSelectors.basePackage(basePackage))
.paths(PathSelectors.ant(antPattern))
.build()
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("API Documentation")
.description("Documentation for API")
.version("1.0")
.build();
}
}
启动后访问:
http://localhost:8080/swagger-ui.html
@EnableWebMvc 用于导入 Spring Web MVC configuration(配置类 @Configuration 上)
将此注释添加到 @Configuration 类将导入来自 WebMvcConfigurationSupport 的 Spring MVC配置。
@EnableWebMvc == @Import({DelegatingWebMvcConfiguration.class})
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "controller")
@PropertySource(value = "classpath:application.yaml", ignoreResourceNotFound = true, encoding = "UTF-8")
public class WebMvcAutoConfiguration implements WebMvcConfigurer {
//文件协议
private static final String FILE_PROTOCOL = "file:///";
//配置信息实体
private final HaloProperties haloProperties;
//自动注入HaloProperties
public WebMvcAutoConfiguration(HaloProperties haloProperties) {
this.haloProperties = haloProperties;
}
/**
* Spring Boot底层通过HttpMessageConverters(依靠Jackson库)将Java实体类输出为JSON格式。
*
* MappingJackson2HttpMessageConverter可以将Java对象转换为application/json。
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.stream()
.filter(c -> c instanceof MappingJackson2HttpMessageConverter)
// ifPresent():如果存在一个值,则使用该值执行给定的操作,否则什么也做不成
.findFirst().ifPresent(converter ->
{
// MappingJackson2HttpMessageConverter:读写Json转换器
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) converter;
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
// JsonComponentModule 来扫描被 @JsonComponent 注解的类,
// 并自动注册 JsonSerializer 和 JsonDeserializer。
JsonComponentModule module = new JsonComponentModule();
// addSerializer():为序列化模块添加自定义序列化程序来处理特定类型的值。
// PageJacksonSerializer:Page对象的序列化
module.addSerializer(PageImpl.class, new PageJacksonSerializer());
// builder.modules():指定序列化模块
ObjectMapper objectMapper = builder.modules(module).build();
// 设置自定义 objectMapper,未设置则使用默认 objectMapper
mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
});
}
/**
* 自定义参数处理器
*/
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new AuthenticationArgumentResolver());
}
/**
* 配置静态资源路径
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String workDir = FILE_PROTOCOL + haloProperties.getWorkDir();
//映射 /** 的请求到 addResourceLocations() 指定的目录
registry.addResourceHandler("/**")
.addResourceLocations(workDir + "templates/themes/")
}
/**
* 添加转换器(Converter)和格式器(Formatters)
*/
@Override
public void addFormatters(FormatterRegistry registry) {
//ConverterFactory:range范围转换器的工厂(可以将对象从S转换为R的子类型)
registry.addConverterFactory(new StringToEnumConverterFactory());
}
/**
* 配置 freemarker
*/
@Bean
public FreeMarkerConfigurer freemarkerConfig(HaloProperties haloProperties) throws IOException, TemplateException {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
//设置模板路径与字符集
configurer.setTemplateLoaderPaths(FILE_PROTOCOL + haloProperties.getWorkDir() + "templates/", "classpath:/templates/");
configurer.setDefaultEncoding("UTF-8");
Properties properties = new Properties();
properties.setProperty("auto_import", "/common/macro/common_macro.ftl as common,/common/macro/global_macro.ftl as global");
configurer.setFreemarkerSettings(properties);
return configurer;
}
/**
* 配置视图解析器来转换基于字符串的视图名称
*/
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
resolver.setCache(false);
resolver.setSuffix(HaloConst.SUFFIX_FTL);
resolver.setContentType("text/html; charset=UTF-8");
registry.viewResolver(resolver);
}
}
@PropertySource 加载指定的配置文件到 Spring 的 Environment 中(配置类 @Configuration 上)
@PropertySource(value = "classpath:application.yaml",
ignoreResourceNotFound = true, encoding = "UTF-8") //true表示属性源是可选的
用于 PropertySource 在 Spring 的上 添加 Environment。与 @Configuration 类一起使用。
获取配置文件中的值通过 Environment 具体使用方法:
@Autowired
private Environment env;
或者
使用 @value 注解,从配置文件读取值:
@Value("${test.value}")
HandlerMethodArgumentResolver 自定义参数解析
自定义解析器需要实现 HandlerMethodArgumentResolver 接口。
实现自定义参数解析器步骤:1、自定义注解 2、自定义参数解析器 3、注册 4、在需要注入属性的 controller 添加注解
自定义注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface UserToken {String value() default "user";}
自定义参数解析器:
@Component
public class AuthenticationArgumentResolver implements HandlerMethodArgumentResolver {
/**
* 解析器是否支持当前参数
*/
@Override
public boolean supportsParameter(MethodParameter parameter) {
// 指定参数如果被应用 UserToken 注解,则使用该解析器。
// 如果直接返回true,则代表将此解析器用于所有参数
return parameter.hasParameterAnnotation(UserToken.class);
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) {}
}
注册:
public class WebMvcAutoConfiguration implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new AuthenticationArgumentResolver());
}
}
序列化和反序列化
层次低的一种是 Byte <---> Message,二进制与程序内部消息对象之间的转换,就是常见的序列化/反序列化。
另外一种是 Message <---> Message,程序内部对象之间的转换,比较高层次的序列化/反序列化。
Http序列化和反序列化(高层次)的核心是HttpMessageConverter。
@JsonSerialize @JsonDeserialize @JsonComponent
如果使用 Jackson 序列化和反序列化 JSON 数据,
您可能需要编写自己的 JsonSerializer 和 JsonDeserializer 类。
自定义序列化程序通常通过模块向 Jackson 注册,
但 Spring Boot 提供了另一种 @JsonComponent 注释,可以更容易地直接注册 Spring Beans。
您可以直接在 JsonSerializer 或 JsonDeserializer 实现上使用 @JsonComponent 注释。
您还可以在包含 JsonSerializer 或 JsonDeserializer 作为内部类的类上使用它。
@JsonSerialize:
可以实现数据转换功能,此注解用于属性或者 getter() 方法上。
@JsonDeserialize:
此注解用于属性或者 setter() 方法上,用于在反序列化时可以嵌入我们自定义的代码。
@JsonComponent:
注释允许我们将带注释的类公开为Jackson序列化器和/或反序列化器,而无需手动将其添加到ObjectMapper。
@JsonSerialize(using = JsonDateSerialize.class)
@JsonDeserialize(using = JsonDateDeserialize.class)
private Date birthday;
Halo(二)的更多相关文章
- Halo 开源项目学习(二):实体类与数据表
基本介绍 Halo 项目中定义了一些实体类,用于存储博客中的关键数据,如用户信息.文章信息等.在深入学习 Halo 的设计理念与实现过程之前,不妨先学习一下一个完整的博客系统都由哪些元素组成. 实体类 ...
- Halo(十二)
@RequestBody @ResponseBody @RequestBody 1) 该注解用于读取 Request 请求的 body 部分数据,使用系统默认配置的 HttpMessageConver ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十二 || 三种跨域方式比较,DTOs(数据传输对象)初探
更新反馈 1.博友@落幕残情童鞋说到了,Nginx反向代理实现跨域,因为我目前还没有使用到,给忽略了,这次记录下,为下次补充.此坑已填 2.提示:跨域的姊妹篇——<三十三║ ⅖ 种方法实现完美跨 ...
- Unity 编辑器学习(二)之 全局光照(GI)
光影流年,花影阡陌.光与影交织的岁月教育我们,不会使用光照的程序员不是个好美术. 一.概述 点击 Window > Lighting > Settings 会弹出Lighting窗口,这个 ...
- 使用Docker快速搭建Halo个人博客到阿里云服务器上[附加主题和使用域名访问]
一.前言 小编买了一个服务器也是一直想整个网站,一直在摸索,看了能够快速搭建博客系统的教程.总结了有以下几种方式,大家按照自己喜欢的去搭建: halo wordpress hexo vuepress ...
- Nginx反向代理实现Tomcat+Jpress和halo
一.利用Nginx反向代理Jpress+Tomcat 1.环境准备 服务器 IP地址 作用 系统版本 Proxy代理服务器 10.0.0.101 负载均衡Nginx Web服务器 Ubuntu2004 ...
- 【小程序分享篇 二 】web在线踢人小程序,维持用户只能在一个台电脑持登录状态
最近离职了, 突然记起来还一个小功能没做, 想想也挺简单,留下代码和思路给同事做个参考. 换工作心里挺忐忑, 对未来也充满了憧憬与担忧.(虽然已是老人, 换了N次工作了,但每次心里都和忐忑). 写写代 ...
- 前端开发中SEO的十二条总结
一. 合理使用title, description, keywords二. 合理使用h1 - h6, h1标签的权重很高, 注意使用频率三. 列表代码使用ul, 重要文字使用strong标签四. 图片 ...
- 【疯狂造轮子-iOS】JSON转Model系列之二
[疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...
随机推荐
- Halo(十一)
Spring Boot 继承 AbstractErrorController 实现全局异常处理 @RequestMapping("${server.error.path:${error.pa ...
- fileupload组件之上传与下载的页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...
- 查看SQL Server被锁的表以及如何解锁【转】
锁定数据库的一个表的区别 SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除 SELECT * FROM table WITH (TABLO ...
- Gitblit用户没有push权限,但是已经在team里面配置了
问题: 用户已经移动到team里面,team有对应repository的push权限. does not have push permissions for 解决方案: 发现这个用户以前单独配置了这个 ...
- C# Self Injector into non managed process
Hey all, I'm gonna explain you how make a self injecting program in C#.I hope you guys thinks its us ...
- 使用 jQuery 实现 radio 的选中与反选
使用 jQuery 实现 radio 的选中与反选 我们知道在 Html 中当我们选中一个radio后,再次点击该 radio,那么该 radio 依然是一个选中的状态,但是有时我们需要实现这样的逻辑 ...
- CentOS7 防火墙Firewall常用命令
1.firewalld的基本使用 启动: systemctl start firewalld 查看状态: systemctl status firewalld 停止: systemctl disab ...
- SharePoint 2013中PerformancePoint仪表板设计器连接Analysis Services 2012的问题
在SharePoint 2013的PerformancePoint仪表板设计器在创建链接到AnalysisServices 2012的数据链接的时候,数据库列表无法获取服务器上的数据库.这个问题挺让人 ...
- 第一次刷Leetcode,为什么耗费很多时间
Leetcode第2题思考过程分析:耗费的时间与思考过程 1. 审题耗费了很长时间,英文看不懂.两个单链表代表了两个整数,整数逆序,(2 -> 4 -> 3) + (5 -> 6 - ...
- python 装饰器 对类和函数的装饰
#装饰器:对类或者函数进行功能的扩展 很多需要缩进的没有进行缩进'''#第一步:基本函数def laxi(): print('拉屎')#调用函数laxi()laxi() print('======= ...