写文章
写文章需要 三个接口:
获取所有文章类别
获取所有标签
发布文章
1. 所有文章分类
1.1 接口说明
接口url:/categorys
请求方式:GET
请求参数:
参数名称 | 参数类型 | 说明 |
---|---|---|
返回数据:
{
"success":true,
"code":200,
"msg":"success",
"data":
[
{"id":1,"avatar":"/category/front.png","categoryName":"前端"},
{"id":2,"avatar":"/category/back.png","categoryName":"后端"},
{"id":3,"avatar":"/category/lift.jpg","categoryName":"生活"},
{"id":4,"avatar":"/category/database.png","categoryName":"数据库"},
{"id":5,"avatar":"/category/language.png","categoryName":"编程语言"}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
1.2 Controller
package com.mszlu.blog.controller;
import com.mszlu.blog.service.CategoryService;
import com.mszlu.blog.vo.CategoryVo;
import com.mszlu.blog.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("categorys")
public class CategoryController {
@Autowired
private CategoryService categoryService;
@GetMapping
public Result listCategory() {
return categoryService.findAll();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1.3 Service
public CategoryVo copy(Category category){
CategoryVo categoryVo = new CategoryVo();
BeanUtils.copyProperties(category,categoryVo);
return categoryVo;
}
public List<CategoryVo> copyList(List<Category> categoryList){
List<CategoryVo> categoryVoList = new ArrayList<>();
for (Category category : categoryList) {
categoryVoList.add(copy(category));
}
return categoryVoList;
}
@Override
public Result findAll() {
List<Category> categories = this.categoryMapper.selectList(new LambdaQueryWrapper<>());
return Result.success(copyList(categories));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2. 所有文章标签
2.1 接口说明
接口url:/tags
请求方式:GET
请求参数:
参数名称 | 参数类型 | 说明 |
---|---|---|
返回数据:
{
"success": true,
"code": 200,
"msg": "success",
"data": [
{
"id": 5,
"tagName": "springboot"
},
{
"id": 6,
"tagName": "spring"
},
{
"id": 7,
"tagName": "springmvc"
},
{
"id": 8,
"tagName": "11"
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2.2 Controller
@GetMapping
public Result findAll(){
return tagService.findAll();
}
1
2
3
4
2
3
4
2.3 Service
@Override
public Result findAll() {
List<Tag> tags = this.tagMapper.selectList(new LambdaQueryWrapper<>());
return Result.success(copyList(tags));
}
1
2
3
4
5
2
3
4
5
3. 发布文章
3.1 接口说明
接口url:/articles/publish
请求方式:POST
请求参数:
参数名称 | 参数类型 | 说明 |
---|---|---|
title | string | 文章标题 |
id | long | 文章id(编辑有值) |
body | object({content: "ww", contentHtml: " ww ↵"}) | 文章内容 |
category | {id: 2, avatar: "/category/back.png", categoryName: "后端"} | 文章类别 |
summary | string | 文章概述 |
tags | [{id: 5}, {id: 6}] | 文章标签 |
返回数据:
{
"success": true,
"code": 200,
"msg": "success",
"data": {"id":12232323}
}
1
2
3
4
5
6
2
3
4
5
6
3.2 Controller
package com.mszlu.blog.vo.params;
import com.mszlu.blog.vo.CategoryVo;
import com.mszlu.blog.vo.TagVo;
import lombok.Data;
import java.util.List;
@Data
public class ArticleParam {
private Long id;
private ArticleBodyParam body;
private CategoryVo category;
private String summary;
private List<TagVo> tags;
private String title;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.mszlu.blog.vo.params;
import lombok.Data;
@Data
public class ArticleBodyParam {
private String content;
private String contentHtml;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
@PostMapping("publish")
public Result publish(@RequestBody ArticleParam articleParam){
return articleService.publish(articleParam);
}
1
2
3
4
2
3
4
3.3 Service
@Override
@Transactional
public Result publish(ArticleParam articleParam) {
SysUser sysUser = UserThreadLocal.get();
Article article = new Article();
article.setAuthorId(sysUser.getId());
article.setCategoryId(articleParam.getCategory().getId());
article.setCreateDate(System.currentTimeMillis());
article.setCommentCounts(0);
article.setSummary(articleParam.getSummary());
article.setTitle(articleParam.getTitle());
article.setViewCounts(0);
article.setWeight(Article.Article_Common);
article.setBodyId(-1L);
this.articleMapper.insert(article);
//tags
List<TagVo> tags = articleParam.getTags();
if (tags != null) {
for (TagVo tag : tags) {
ArticleTag articleTag = new ArticleTag();
articleTag.setArticleId(article.getId());
articleTag.setTagId(tag.getId());
this.articleTagMapper.insert(articleTag);
}
}
ArticleBody articleBody = new ArticleBody();
articleBody.setContent(articleParam.getBody().getContent());
articleBody.setContentHtml(articleParam.getBody().getContentHtml());
articleBody.setArticleId(article.getId());
articleBodyMapper.insert(articleBody);
article.setBodyId(articleBody.getId());
articleMapper.updateById(article);
ArticleVo articleVo = new ArticleVo();
articleVo.setId(article.getId());
return Result.success(articleVo);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.mszlu.blog.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mszlu.blog.dao.pojo.ArticleTag;
public interface ArticleTagMapper extends BaseMapper<ArticleTag> {
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
package com.mszlu.blog.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mszlu.blog.dao.pojo.ArticleBody;
public interface ArticleBodyMapper extends BaseMapper<ArticleBody> {
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
package com.mszlu.blog.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import java.util.List;
@Data
public class ArticleVo {
//一定要记得加 要不然 会出现精度损失
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
private String title;
private String summary;
private Integer commentCounts;
private Integer viewCounts;
private Integer weight;
/**
* 创建时间
*/
private String createDate;
private String author;
private ArticleBodyVo body;
private List<TagVo> tags;
private CategoryVo category;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.mszlu.blog.dao.pojo;
import lombok.Data;
@Data
public class ArticleTag {
private Long id;
private Long articleId;
private Long tagId;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
当然登录拦截器中,需要加入发布文章的配置:
@Override
public void addInterceptors(InterceptorRegistry registry) {
//拦截test接口,后续实际遇到需要拦截的接口时,在配置为真正的拦截接口
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/test")
.addPathPatterns("/comments/create/change")
.addPathPatterns("/articles/publish");
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
3.4 测试
4. AOP日志
package com.mszlu.blog.common.aop;
import java.lang.annotation.*;
/**
* 日志注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {
String module() default "";
String operation() default "";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.mszlu.blog.common.aop;
import com.alibaba.fastjson.JSON;
import com.mszlu.blog.utils.HttpContextUtils;
import com.mszlu.blog.utils.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
/**
* 日志切面
*
*/
@Aspect
@Component
@Slf4j
public class LogAspect {
@Pointcut("@annotation(com.mszlu.blog.common.aop.LogAnnotation)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
//执行方法
Object result = point.proceed();
//执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//保存日志
recordLog(point, time);
return result;
}
private void recordLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
log.info("=====================log start================================");
log.info("module:{}",logAnnotation.module());
log.info("operation:{}",logAnnotation.operation());
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
log.info("request method:{}",className + "." + methodName + "()");
// //请求的参数
Object[] args = joinPoint.getArgs();
String params = JSON.toJSONString(args[0]);
log.info("params:{}",params);
//获取request 设置IP地址
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
log.info("ip:{}", IpUtils.getIpAddr(request));
log.info("excute time : {} ms",time);
log.info("=====================log end================================");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73