文章微服务属于微服务社交项目的文章版块功能,这个功能主要讲解查询文章列表接口服务和spring data redis缓存使用。
上篇文章主要讲解了招聘微服务的职位列表信息查询以及热门企业查询服务,本次课程主要讲解文章微服务spring boot工程的搭建以及开发文章微服务功能。
头部属于菜单功能区,内容主体分为左边文章频道区和右侧文章列表区。左边文章频道查询接口和右侧文章列表信息查询接口。
项目采用spring boot多模块构建,后期会加入spring cloud构建工程,目前已经拆分为微服务。
项目依赖于tensquare_base、tensquare_common2个微服务模块。
微服务模块为tensquare_article
tensquare_article
点击完成,完成新建模块
<?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">
<parent>
<artifactId>tensquare_parent</artifactId>
<groupId>com.tensquare</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.tensquare</groupId>
<artifactId>tensquare_article</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis依赖commons-pool 这个依赖一定要添加 -->
<!--<dependency>-->
<!--<groupId>io.lettuce</groupId>-->
<!--<artifactId>lettuce-core</artifactId>-->
<!--</dependency>-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.tensquare</groupId>
<artifactId>tensquare_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
server:
port: 9005
spring:
application:
name: tensquare_article #指定服务名
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/tensquare_article?characterEncoding=UTF8
username: root
password: root
jpa:
database: MySQL
show-sql: true
redis:
host: 127.0.0.1
port: 6379
为了防止前后端分离请求跨域请求失败新增配置类如下:
```java
package com.tensquare.article.config;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setContentType("textml;charset=UTF-8");
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "0");
response.setHeader("Access-Control-Allow-Headers","Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("XDomainRequestAllowed", "1");
chain.doFilter(req, res);
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
package com.tensquare.article.controller;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.tensquare.article.pojo.Article;
import com.tensquare.article.service.ArticleService;
import entity.PageResult;
import entity.Result;
import entity.StatusCode;
/**
* 控制器层
* @author Administrator
*
*/
@RestController
@CrossOrigin
@RequestMapping("/article")
public class ArticleController {
@Autowired
private ArticleService articleService;
/**
* 根据ID查询
* @param id ID
* @return
*/
@RequestMapping(value="/{id}",method= RequestMethod.GET)
public Result findById(@PathVariable String id){
return new Result(true,StatusCode.OK,"查询成功",articleService.findById(id));
}
/**
* 分页+多条件查询
* @param searchMap 查询条件封装
* @param page 页码
* @param size 页大小
* @return 分页结果
*/
@RequestMapping(value="/search/{page}/{size}",method=RequestMethod.POST)
public Result findSearch(@RequestBody Map searchMap , @PathVariable int page, @PathVariable int size){
Page<Article> pageList = articleService.findSearch(searchMap, page, size);
return new Result(true,StatusCode.OK,"查询成功", new PageResult<Article>(pageList.getTotalElements(), pageList.getContent()) );
}
/***
* 文章审核
*/
@RequestMapping(value = "/examine/{id}")
public Result examine(@PathVariable String id){
articleService.examine(id);
return new Result(true,StatusCode.OK,"审核成功");
}
/**
* 文章点赞
*/
@RequestMapping(value = "/thumbsup/{id}")
public Result updatethumbsup(@PathVariable String id){
articleService.thumbsup(id);
return new Result(true,StatusCode.OK,"点赞成功");
}
}
表名:tb_article
字段 | 中文名 |
---|---|
id | 文章主键ID |
title | 文章标题 |
content | 文章内容 |
createtime | 创建时间 |
thumbup | 点赞数 |
state | 审核状态 |
channelid | 所属频道 |
表名:tb_channel
字段 | 中文名 |
---|---|
id | 频道ID |
name | 频道名称 |
state | 频道状态 |
根据文章ID,后台运营管理员审核文章通过才能显示到前台首页头条中,
更新文章表state字段为1
用户对某一篇文章进行点赞,根据文章Id,找到文章将文章中的thumbup+1,进行点赞数增加。
由于用户频繁查询文章信息,为了优化根据ID查询文章的接口,可以使用spring-data-redis来将文章信息存储到redis中,如果redis中存在则用户去redis缓存中去获取文章信息。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
@Resource
private RedisTemplate redisTemplate;
/***
* 首先查询redis
*/
Article article= (Article) redisTemplate.opsForValue().get("article_"+id);
if(article==null){
//查询数据库
article=articleDao.findById(id).get();
//查询出来放入缓存 //过期时间控制
redisTemplate.opsForValue().set("article_"+id,article,100, TimeUnit.SECONDS);
}
return article;
由于当用户删除或者更新文章的时候,前台如果还从redis获取缓存数据有的时候会不准确所以,在删除和修改文章的时候需要删除redis缓存。
public void update(Article article) {
redisTemplate.delete( "article_" + article.getId() );//删除缓存
articleDao.save(article);
}
经验是由一点一点积累的,思维也是由一天一天训练出来的。
如果你急需一个单体结构项目练手下面的项目可能适合你,可以学习一个完整的项目流程,项目业务以及前后端项目的常用技术:电商在线演示地址为:演示地址
持续更新分享此项目微服务架构项目实战(开发中…)