使用SpringBoot和Redis构建个人博客(二)
上一篇讲了redis sentinel环境的搭建,这一篇进入正题,搭建SpringBoot环境。首先看下搭建完成后的项目结构,再分解讲解一下。
项目结构.jpg
-
BlogWebApplication.java
是启动类 - configuration 包含spring的配置类
- utils 包含所有的工具类
- dto 数据实体类
- controller,service和dao就不用说了,里面分为接口和实现类。
- application.properties和logback-spring.xml是springboot默认读取的应用和日志配置文件,放在resource目录下面
POM文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.blog</groupId>
<artifactId>redis-blog</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>redis-blog</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring.boot.version>1.5.2.RELEASE</spring.boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- 加入redis支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 引入fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- 工具包 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<!-- 引入jsoup解析html -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
</dependencies>
<build>
<finalName>redis-blog</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
POM主要的依赖项如下:
- spring-boot-starter-web基本上涵盖了所有web开发使用到的依赖包
- spring-boot-starter-data-redis需要手工引入,用来连接Redis。
- 比起springboot默认使用的jackson,阿里开源的fastjson api更加简单易用,所以项目中会使用fastjson做http请求的converter。同时放入redis中的数据也使用fastjson来做序列化和反序列化。
- jsoup是一个开源的html parser工具包,用来在用户提交博客时过滤非法的html标签,防止XSS攻击代码提交。
POM写好后就可以导入自己熟悉的IDE里面了,idea可以使用File->New -> Project From Source 从pom导入, 或者Project->New->Project From Version Control->Git。
Eclipse建议先使用mvn eclipse:eclipse生成eclipse工程,然后import project。详细步骤可上网查询。
application.properties
springboot的配置项如下:
spring.profiles.active=dev #表示dev环境
#redis,下面注释的两项单机模式时配置
#spring.redis.hostName=localhost
#spring.redis.port=6379
spring.redis.password=Blog2018dev$ #redis密码,在上一章的redis.conf中有配置
spring.redis.sentinel.master=master001 #master组的名字,在上一章的redis.conf中有配置
spring.redis.sentinel.nodes=127.0.0.1:26379 #sentinel的ip和密码,多个的话使用逗号隔开
#Redis连接池配置,2.0之前springboot默认使用jedis连接池
spring.redis.pool.max-active=200
spring.redis.pool.max-idle=10
spring.redis.pool.min-idle=0
spring.redis.pool.max-wait=5000
spring.redis.timeout=30000
#http默认编码,貌似不配也可以
spring.http.encoding.charset=UTF-8
app.log.path=logs # 日志文件路径,logback-spring.xml中有用到
以上的配置文件中redis相关配置是必须的,连接池springboot会有默认配置,可根据自己需要选择修改其中一个或者多个
Redis Template基础配置
springboot配置中加入redis配置后,spring会默认生成一个RedisTemplate
的Bean,只要业务代码里将这个Bean注入就可以使用redis了。不过为了使用起来更方便,我们需要额外做一些配置。
- Springboot 默认使用java自带的序列化类来序列化value,因为序列化后的value是不可读的,所以我们改成
使用json序列化。 - 写一个
RedisSupport
类封装redis操作,便于Dao中使用 - 一个Configuration将上面的配置生效
首先需要实现一个RedisSerializer
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>{
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
public FastJson2JsonRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
//使用fastjson做序列化,同时带上class name,便于反序列化
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz);
}
}
Configuration类,做两件事情,定义RedisSupport
Bean,将RedisTemplate
序列化类改成我们上面写的使用fastjson的实现。
@Configuration
public class RedisConfiguration {
@Bean
@Primary
public RedisTemplate<String, Object> createRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new FastJson2JsonRedisSerializer<>(Object.class)); //普通value
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new FastJson2JsonRedisSerializer<>(Object.class)); //Hash结构的Value
// redisTemplate.setEnableTransactionSupport(true); //这里不要打开事务支持,原因后面单独写一篇文章来解释
return redisTemplate;
}
/**
* 定义RedisSupport bean
*/
@Bean(name = "redisSupport")
public RedisSupport createRedisSupport(RedisTemplate<String, Object> redisTemplate) {
return new RedisSupport(redisTemplate);
}
}
RedisSupport
类,封装了RedisTemplate
的操作。这里只截取一个片段,详细的请到git上查看。
public class RedisSupport {
private RedisTemplate<String, Object> redisTemplate;
/**
* 根据key 获取过期时间
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key){
return redisTemplate.getExpire(key,TimeUnit.SECONDS);
}
/**
* 判断key是否存在
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key){
return exists(key);
}
public boolean exists(String key) { return redisTemplate.hasKey(key);}
/**
* 删除缓存
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String ... key){
if(key!=null&&key.length>0){
if(key.length==1){
redisTemplate.delete(key[0]);
}else{
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
}
好了,redis的配置到这里就结束了,后面就可以在Dao里愉快的使用RedisSupport
了,具体用法就是在Dao中注入RedisSupport
就可以了。
比如ArticleDao中获取一篇文章的属性,详细的代码见Git上
@Repository
public class ArticleDaoImpl implements ArticleDao {
private final Logger log = LoggerFactory.getLogger(ArticleDao.class);
@Autowired
private RedisSupport redisSupport; //注入RedisSupport
@Override
public ArticleDto getSummary(Long id) {
Assert.notNull(id, "id must not be null");
//从redis中取一篇文章的属性,文章使用Hash类型存储
Map<Object,Object> result = redisSupport.hmget("article:"+id);
if(MapUtils.isNotEmpty(result)){
ArticleDto article = BeanUtils.mapToBean(result, ArticleDto.class);
if(NumberUtils.zeroOnNull(article.getStatus()) <= 1)
return article;
}
return null;
}
}
Spring mvc 配置
spring mvc的配置我们只干一件事,使用fastjson代替jackson来转换http的request和将reponse转成json。实现方式很简单,fastjson已经提供了一个converter类的实现FastJsonHttpMessageConverter
,
只需要用它作为默认的converter就可以了。修改Spring mvc的配置一般是通过继承WebMvcConfigurationSupport
,并重写其中的方法来实现的。
@Configuration
public class WebConfiguration extends WebMvcConfigurationSupport{
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
//SerializerFeature.PrettyFormat reponse返回的json做format,带回车和缩进,如果为了节省流量可在发正式环境时去掉
//SerializerFeature.WriteDateUseDateFormat 转json时将日期转成yyyy-MM-dd HH:mm:ss的格式
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat, SerializerFeature.WriteDateUseDateFormat);
fastConverter.setFastJsonConfig(fastJsonConfig);
fastConverter.setDefaultCharset(Charset.forName("UTF-8"));
//content-type未application/json的请求将会使用这个converter
fastConverter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON_UTF8,MediaType.APPLICATION_JSON));
HttpMessageConverter<Object> converter = fastConverter;
//将converter放在第一个,优先匹配
converters.add(0, converter);
}
}
SpringBoot+Redis配置已经讲完了,下一章将讲使用Redis存储个人博客系统的数据结构设计,并跑通一个完整的请求。
参考文章:https://blog.csdn.net/qq_34021712/article/details/75949706 ©王赛超