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

spring init

As shown above, through Spring’s officialSpring InitialThe site generates projects with the following directory structure:

  • 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.