新增文章接口
业务需求:
当用户在点击左侧菜单列表里边,在右侧这个页面里边去展示当前文章相关的内容,在右侧页面的右上角会有一个发布文章按钮,当用户点击按钮时,会弹出一个抽屉的界面,在这个抽屉的界面里有一个表单,用户需要在表单里输入文章的标题,文章分类,选择文章的封面图像,再去填写一下文章的内容,如果都填写了没有问题,那么此时就可以点击发布按钮,访问后台的接口。
实现思路:
需要在Controller中编译方法,在service层完成业务代码。
代码展示:
controller层:
@PostMapping
public Result<String> add(@RequestBody Article article) {
articleService.add(article);
return Result.success();
}
Service层:
public void add(Article article) {
//将创建时间,修改时间设置为当前时间
article.setCreateTime(LocalDateTime.now());
article.setUpdateTime(LocalDateTime.now());
//获取当前用户id
Map<String,Object> map = ThreadUtil.get();
Integer id = (Integer) map.get("id");
//设置创建用户id
article.setCreateUser(id);
//保存
articleMapper.save(article);
mapper层:
@Update("insert into article(title,content,cover_img,state,category_id,create_user,create_time,update_time) values(#{title},#{content},#{coverImg},#{state},#{categoryId},#{createUser},#{createTime},#{updateTime})")
void save(Article article);
测试:
测试成功,在进行对参数的校验。
参数校验
需要在实体类上进行参数校验。
@Data
@AllArgsConstructor
@NoArgsConstructor
@Validated
public class Article {
private Integer id;//主键ID
@NotEmpty
@Pattern(regexp = "^\\S{1,10}$")
private String title;//文章标题
private String content;// 文章内容
@NotEmpty
@URL
private String coverImg;// 封面图片
private String state;//发布状态(已发布/草稿)
@NotNull
private Integer categoryId;//分类ID
private Integer createUser;//创建者ID
private LocalDateTime createTime;//创建时间
private LocalDateTime updateTime;//修改时间
}
注意要在controller层上添加注解:
public Result<String> add(@RequestBody @Validated Article article) {
articleService.add(article);
return Result.success();
}
测试:
但是我们状态的校验用注解已经无法是实现了,因此需要自定义校验。
自定义校验
已有的注解不能满足所有的校验需求,特殊的情况需要自定义校验,(自定义校验注解)
实现步骤
自定义注解state
自定义校验数据的State Validation实现ConstraintValidator接口
在需要校验的地方使用自定义注解
代码展示:
@State
package com.lyc.annotation;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;
@Documented
//在属性上生效
@Target(ElementType.FIELD)
//在运行时阶段保留
@Retention(RetentionPolicy.RUNTIME)
// 自定义注解 提供校验规则
@Constraint(validatedBy = StateValidation.class)
public @interface State {
//提供校验失败后的提示信息
String message() default "文章状态只能是:已发布或者草稿";
//指定分组
Class[] groups() default {};
//负载,获取到该自定义注解的附加信息
Class<? extends Payload>[] payload() default{};
}
StateValidation
package com.lyc.annotation;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
//泛型中提供的第一个参数是给那个注解提供给校验规则,第二个参数是校验的数据类型
public class StateValidation implements ConstraintValidator<State, String> {
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
/**
* @Param s 将来要校验的数据
* @return
*/
//提供校验规则
if (s == null){
return false;
}
if (s.equals("已发布") || s.equals("草稿")){
return true;
}
return false;
}
}
进行测试:
证明注解成功。
总结:
自定义校验
自定义校验State,message,groups,payload
自定义校验数据的类state Validation
在需要校验的地方使用自定义注解
文章列表(条件分页)
业务需求:
当用户在点击左侧菜单列里面的文章管理后,在页面的主区域展示当前用户创建的文章信息,并且这些文章是以列表的形式去展示,在列表的上方,可以选择文章分类,发布状态去搜索文章,在列表的底部,他去展示了一个分页条,里面展示了总记录数,还有一些用户的可选择项,用户可以选择每一页显示的条数,以及查询页码,上一页,下一页等等,都需要去访问后端接口,拿到数据,达到明确的要求,最终在列表中进行展示
查看接口文档:
实现思路:
在Controller中添加方法,完成列表查询。根据返回数据的返回结果去自定义pageBean类,需要去拿到封装分页查询的结果,需要去自定义。
然后在方法内部调用service层的方法查询。
在service层需要使用mybatis提供的pageHelper完成分页查询,我们只需要在调用mapper的方法执行SQL语句之前开启分页查询。
然后在mapper层编译动态SQL。
代码展示:
controller层:
public Result<PageBean<Article>> list(Integer pageNum,Integer pageSize,
@RequestParam(required = false) Integer categoryId,
@RequestParam(required = false) String state){
PageBean<Article> list = articleService.list(pageNum, pageSize, categoryId, state);
return Result.success(list);
}
Service层:
public PageBean<Article> list(Integer pageNum, Integer pageSize, Integer categoryId, String state) {
//1. 构建Page Bean对象
Map<String,Object> map= ThreadUtil.get();
Integer userid = (Integer) map.get("id");
PageBean<Article> pageBean = new PageBean<>();
//开启分页查询 pageHelper
PageHelper.startPage(pageNum,pageSize);
//调用mapper完成查询
List<Article> as = articleMapper.list(userid,categoryId,state);
//Page中提供了方法,可以获取PageHelper分页查询后,得到的总记录条数和当前页数据
Page<Article> p = (Page<Article>) as;
//把数据填充到pageBean对象中
pageBean.setTotal(p.getTotal());
pageBean.setItems(p.getResult());
return pageBean;
}
mapper层:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lyc.mapper.ArticleMapper">
<!-- 动态SQL-->
<select id="list" resultType="com.lyc.pojo.Article">
select * from article
<where>
<if test="categoryId != null">
category_id = #{categoryId}
</if>
<if test="state != null">
and state = #{state}
</if>
and create_user = #{userid}
</where>
</select>
</mapper>
注意事项:
在controller层中需要注意添加@RequestParam(required = false)注解。
在Service层中需要使用pageHelper完成分页查询,需要在pom配置文件中导入pageHelper
我们查询的结果是类似的集合需要向下强转,把它转化成一个Page对象,page是list的一个实现类
mapper层不要使用注解,因为是编译动态SQL,使用映射配置文件的方式更加方便。
获取文章详情
明确业务需求:点击文章列表中的条目即可看到指定文章的详细信息。
查询接口文档:
代码实现:
在接口文档中隐藏了createUser,因此我们可以在pojo包中新建ArticleDTO实体类,隐藏部分信息。
package com.lyc.pojo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ArticleDTO {
private Integer id;//主键ID
private String title;//文章标题
private String content;// 文章内容
private String coverImg;// 封面图片
private String state;//发布状态(已发布/草稿)
private Integer categoryId;//分类ID
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime createTime;//创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime updateTime;//修改时间
}
在编译Controller层代码:
@GetMapping("/detail")
public Result<ArticleDTO> detail(Integer id){
ArticleDTO article = articleService.detail(id);
return Result.success(article);
}
service层:
public ArticleDTO detail(Integer id) {
return articleMapper.detail(id);
}
mapper层:
<select id="detail" resultType="com.lyc.pojo.ArticleDTO">
select id,title,content,cover_img,state,category_id,
DATE_FORMAT(create_time, '%Y-%m-%d %H:%i:%s') AS createTime,
DATE_FORMAT(update_time, '%Y-%m-%d %H:%i:%s') AS updateTime
from article where id = #{id}
</select>
进行测试:
测试成功,业务完成
更新文章
业务分析:弹出表单供客户修改,并最终写入数据库。
查看接口文档并编译代码:
controller:
@PutMapping
public Result update(@RequestBody @Validated ArticleDTO article) {
articleService.update(article);
return Result.success();
}
service:
public void update(ArticleDTO article) {
articleMapper.update(article);
}
mapper:
@Update("update article set title = #{title},content = #{content},cover_img = #{coverImg},state = #{state},category_id = #{categoryId},update_time = now() where id = #{id}")
void update(ArticleDTO article);
进行测试:
测试成功,业务完成。
删除文章
业务分析:通过id删除文章
查看接口文档:
代码展示:
controller:
@DeleteMapping
public Result delete(Integer id) {
articleService.delete(id);
return Result.success();
}
Service:
public void delete(Integer id) {
articleMapper.delete(id);
}
mapper:
@Update("delete from article where id = #{id}")
void delete(Integer id);
进行测试:
查看数据库:
测试成功,业务实现。
希望对大家有所帮助