As a back-end developer, in the era of microservices, Server Mesh and other concepts, continuous learning ability cannot be lost. Therefore, the author has recently studied a lot of RPC, NETTY, Spring Boot and other technologies. In addition, the reading statistics function of the host blog uses a third party statistics function that matches HEXO, thus creating the host’s own self-developed base function for the tour.
Generate the project through SPRING INITIALIZR
- The directory structure
-src-main-java-package If Tomcat, Jetty, Undertow, etc. is running, then run it -SpringbootApplication -resouces # store static resources js/ CSS /images, etc. - statics # store HTML template files - Templates # Main configuration file, SpringBoot start automatically when loading the application. The yml/application. The properties - application. Yml # # test file storage directory - test pom. The XML file is the foundation of the Maven build, It contains information about the JAR and Plugin we rely on - POMCopy the code
- Pom depends on
<? The 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" > The < 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 - the 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> Mons < groupId > org.apache.com < / 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> </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>Copy the code
Implement redis storage logic
The reason for choosing Redis over databases is that Redis provides rich data structures and data persistence strategies, and redis is memory-based, which is more than an order of magnitude faster than databases. However, the scene of counting the number of reads still has certain requirements on the speed of interface processing. Therefore, redis is selected as the DB of counting the number of reads. The following is the basic code of redis operation, relatively simple building main post code, without further elaboration
-
Redis interface class
public interface RedisService { public boolean set(final String key, final String value); public String get(final String key); public String incr(final String key); } Copy the code
-
Redis implementation class
@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; }}Copy the code
Blog reading times statistics interface implementation
The basic business logic of blog read count is that the blogId corresponding to each blog is the key of redis, and the number of visits is the value corresponding to this key. Each visit to the interface will increment the corresponding blogId once and return the corresponding value. Stirng redis data structure Stirng redis data structure Stirng redis data structure Stirng
** @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; }}}Copy the code
Potholes encountered during implementation
- Set the port number for starting the application
server.port=9401
Copy the code
- Set the path for application access
The default path of the Spring Boot application is still “/”. The default path of the Spring Boot application is “/”. The default path is “/”
Server. The servlet. The context path = / project nameCopy the code
summary
In addition, this article is based on the latest spring-boot-starter-parent: 2.0.3.RELEASE.
extra
LIGHTCONF is a configuration management platform based on Netty implementation. Its core design goal is to “provide unified configuration management services for business”, which can be done out of the box. Interested to give a star support.