作为一个后端开发,在微服务,server mesh等概念满天飞的时代,持续学习能力是不能丢的,因此楼主最近也研究好多RPC,NETTY,Spring Boot等技术。此外,楼主博客的阅读统计功能是用的是与HEXO相匹配的第三方的数量统计功能,也就诞生了楼主这次更换成自己开发的基础功能的装逼之旅。
通过SPRING INITIALIZR生成工程
如上图,通过Spring官方的 Spring Initial 网站生成项目,项目的目录结构如下:
- 目录结构
- src
-main
-java
-package
#主函数,启动类,运行它如果运行了 Tomcat、Jetty、Undertow 等容器
-SpringbootApplication
-resouces
#存放静态资源 js/css/images 等
- statics
#存放 html 模板文件
- templates
#主要的配置文件,SpringBoot启动时候会自动加载application.yml/application.properties
- application.yml
#测试文件存放目录
-test
# pom.xml 文件是Maven构建的基础,里面包含了我们所依赖JAR和Plugin的信息
- pom
- 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.*</groupId>
<artifactId>*-*</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>base-service</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.almende.eve</groupId>
<artifactId>eve-bundle-full</artifactId>
<version>3.1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
实现redis存储逻辑
选择redis而没选择数据库的原因是redis提供了丰富的数据结构与数据持久化策略,另外redis是基于内存的,相对于数据库来说,快了不止一个数量级。而统计阅读次数的场景对接口处理的速度还是有一定的要求的,因此楼主选择了redis作为阅读次数统计的db。
下面就是redis操作的基础代码,比较简单楼主贴一下代码,不做进一步的阐述
- redis的接口类 public interface RedisService { public boolean set(final String key, final String value); public String get(final String key); public String incr(final String key); }
- redis的实现类
@Service
public class RedisServiceImpl implements RedisService {
@Resource
private RedisTemplate<String, ?> redisTemplate;
@Override
public boolean set(final String key, final String value) {
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
connection.set(serializer.serialize(key), serializer.serialize(value));
return true;
}
});
return result;
}
@Override
public String incr(final String key) {
String incr = redisTemplate.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection redisConnection) throws DataAccessException {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
Long value = redisConnection.incr(serializer.serialize(key));
return String.valueOf(value);
}
});
return incr;
}
@Override
public String get(final String key){
String result = redisTemplate.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
byte[] value = connection.get(serializer.serialize(key));
return serializer.deserialize(value);
}
});
return result;
}
}
博客阅读次数统计接口实现
博客阅读次数统计的基本业务逻辑就是,对应每篇博客的blogId作为redis的key,而访问次数就是这个key所对应的value,每访问一次该接口就要将对应的blogId自增一次,并返回对应的value。这里楼主选择的redis的数据结构是redis的Stirng,下面是楼主实现该逻辑的主要代码:
代码语言:javascript复制/**
* 统计博客阅读次数.
*
* @author wuhf
* @Date 2018/6/15 15:59
**/
@RestController
@RequestMapping("/")
public class BlogReadCountController {
private static String ALLOW_REQUEST_URL = "******";
private static String ILLEGAL_CHARACTERS = "*";
private static String DEFAULT_READ_COUNT = "1";
private static Logger logger = LoggerFactory.getLogger(BlogReadCountController.class);
@Autowired
private RedisService redisService;
@ResponseBody
@RequestMapping("/*_*")
public ResultCode blogReadCountIncr(HttpServletRequest request,String blogId) {
ResultCode resultCode = new ResultCode();
try {
logger.info(">>>>>> method blogReadCountIncr exec , request params is : {}",blogId);
String readCount = redisService.get(blogId);
if (StringUtils.isBlank(readCount)) {
if (!blogId.startsWith(ALLOW_REQUEST_URL)||blogId.contains(ILLEGAL_CHARACTERS)) {
resultCode.setCode(Messages.API_ERROR_CODE);
resultCode.setMsg(Messages.API_ERROR_MSG);
return resultCode;
}
redisService.set(blogId,DEFAULT_READ_COUNT);
readCount = DEFAULT_READ_COUNT;
} else {
readCount = redisService.incr(blogId);
}
logger.info(">>>>>> readCount is : {}",readCount);
resultCode.setCode(Messages.SUCCESS_CODE);
resultCode.setMsg(Messages.SUCCESS_MSG);
resultCode.setData(readCount);
return resultCode;
} catch (Exception e) {
e.printStackTrace();
resultCode.setCode(Messages.API_ERROR_CODE);
resultCode.setMsg(Messages.API_ERROR_MSG);
return resultCode;
}
}
}
实现过程中遇到的坑
- 设置应用启动的端口号
server.port=9401
- 设置应用访问的path
Spring Boot应用默认的应用访问的path还是 “/“,楼主在这里吃了点苦头,使用http://项目名:port访问服务,愣是访问不通,在配置文件中设置如下所示
代码语言:javascript复制server.servlet.context-path=/项目名
小结
目前很多大佬都写过关于 SpringBoot 的教程了,如有雷同,请略过不看,本文通过自己的亲身实战以及楼主自己踩到的坑完成的,另外本文是基于最新的 spring-boot-starter-parent:2.0.3.RELEASE编写。
号外
楼主造了一个轮子,LIGHTCONF 是一个基于Netty实现的一个配置管理平台,其核心设计目标是“为业务提供统一的配置管理服务”,可以做到开箱即用。感兴趣的给个star支持一下。
- 基于Netty实现的轻量级分布式应用配置中心
作 者:haifeiWu
原文链接:https://cloud.tencent.com/developer/article/1333286
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。