十次方03、基础子模块-标签功能

本文详细介绍了基于Spring Boot和JPA实现微服务架构下标签管理的全过程,包括模块搭建、CRUD操作、条件查询及异常处理等内容,适用于微服务环境下标签功能的开发与维护。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基础微服务-标签功能

1. 模块搭建tensquare_base

  1. 搭建基础微服务模块tensquare_base , pom.xml引入依赖
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</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>
    
  2. 创建启动类
    package com.tensquare.base;
    
    @SpringBootApplication
    public class BaseApplication {
    
        /**
         * 启动方法
         * @param args
         */
        public static void main(String[] args) {
            SpringApplication.run(BaseApplication.class,args);
        }
    
        /**
         * 准备一个id生成器并且存入spring的容器中
         * @return
         */
        @Bean
        public IdWorker idWorker() {
            return new IdWorker(1,1);
        }
    }
    
    
    提示:IDEA创建main方法的快捷键是 psvm
  3. 在resources下创建application.yml
    server:
    	port: 9001
    spring:
    	application:
    		name: tensquare‐base #指定服务名
    	datasource:
    		driverClassName: com.mysql.jdbc.Driver
    		url: jdbc:mysql://192.168.184.134:3306/tensquare_base?
    		characterEncoding=utf‐8
    		username: root
    		password: 123456
    	jpa:
    		database: MySQL
    		show‐sql: true
    		generate‐ddl: true
    

2. 标签管理-CRUD

2.1 表结构分析

  1. 表名称:tb_label
    字段名称字段含义字段类型备注
    idID文本
    labelname标签名称文本
    state状态文本0:无效 1:有效
    count使用数量整型
    fans关注数整型
    recommend是否推荐文本0:不推荐 1:推荐
  2. 建数据库:
    
    /*!40101 SET NAMES utf8 */;
    
    /*!40101 SET SQL_MODE=''*/;
    
    /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
    /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
    /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
    /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
    CREATE DATABASE /*!32312 IF NOT EXISTS*/`tensquare_base` /*!40100 DEFAULT CHARACTER SET utf8 */;
    
    USE `tensquare_base`;
    
  3. 建表语句:
    /*Table structure for table `tb_label` */
    
    DROP TABLE IF EXISTS `tb_label`;
    
    CREATE TABLE `tb_label` (
      `id` varchar(20) NOT NULL COMMENT '标签ID',
      `labelname` varchar(100) DEFAULT NULL COMMENT '标签名称',
      `state` varchar(1) DEFAULT NULL COMMENT '状态',
      `count` bigint(20) DEFAULT NULL COMMENT '使用数量',
      `recommend` varchar(1) DEFAULT NULL COMMENT '是否推荐',
      `fans` bigint(20) DEFAULT NULL COMMENT '粉丝数',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='标签';
    
    /*Data for the table `tb_label` */
    
    insert  into `tb_label`(`id`,`labelname`,`state`,`count`,`recommend`,`fans`) values 
    
    ('1','java','1',NULL,NULL,NULL),
    
    ('2','PHP','1',NULL,NULL,NULL),
    
    ('3','C++','1',NULL,NULL,NULL),
    
    ('4','python','1',NULL,NULL,NULL);
    

2.2 CRUD的实现

  1. 实体类
    创建com.tensquare.base包,包下创建pojo包 ,包下创建实体类Label

    package com.tensquare.base.pojo;
    
    /**
     * 标签的实体类
     */
    @Entity
    @Table(name = "tb_label")
    public class Label implements Serializable {
    
        @Id
        private String id;
        private String labelname;
        private String state;
        private Integer count;
        private Integer fans;
        private String recommend;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getLabelname() {
            return labelname;
        }
    
        public void setLabelname(String labelname) {
            this.labelname = labelname;
        }
    
        public String getState() {
            return state;
        }
    
        public void setState(String state) {
            this.state = state;
        }
    
        public Integer getCount() {
            return count;
        }
    
        public void setCount(Integer count) {
            this.count = count;
        }
    
        public Integer getFans() {
            return fans;
        }
    
        public void setFans(Integer fans) {
            this.fans = fans;
        }
    
        public String getRecommend() {
            return recommend;
        }
    
        public void setRecommend(String recommend) {
            this.recommend = recommend;
        }
    }
    
    
  2. 创建数据访问接口
    com.tensquare.base包下创建dao包,包下创建LabelDao接口

    package com.tensquare.base.dao;
    
    import com.tensquare.base.pojo.Label;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
    
    /**
     * 标签的持久层接口
     */
    public interface LabelDao extends JpaRepository<Label, String>, JpaSpecificationExecutor<Label> {
    }
    

    JpaRepository提供了基本的增删改查
    JpaSpecificationExecutor用于做复杂的条件查询

  3. 业务逻辑类
    com.tensquare.base包下创建service包,包下创建LabelService类。 在这个类中,我们实现基本的增删改查功能

    package com.tensquare.base.service;
    
    /**
     * 标签的业务层
     */
    @Service
    public class LabelService {
    
        @Autowired
        private LabelDao labelDao;
    
        @Autowired
        private IdWorker idWorker;
    
        /**
         * 查询所有标签
         * @return
         */
        public List<Label> findAll(){
            return labelDao.findAll();
        }
    
        /**
         * 根据id查询
         * @param id
         * @return
         */
        public Label findById(String id) {
            return labelDao.findById(id).get();
        }
    
        /**
         * 保存
         * @param label
         */
        public void save(Label label) {
            //设置id
            label.setId(String.valueOf(idWorker.nextId()));
            labelDao.save(label);
        }
    
        /**
         * 更新
         * @param label
         */
        public void update(Label label) {
            labelDao.save(label);
        }
    
        /**
         * 删除
         * @param id
         */
        public void delete(String id) {
            labelDao.deleteById(id);
        }
    }
    
  4. 控制器类
    com.tensquare.user包下创建controller包,创建UserController

    package com.tensquare.base.web;
    
    /**
     * 标签控制器
     */
    @RestController
    @RequestMapping("/label")
    @CrossOrigin  // 当前的控制器支持跨域访问
    public class LabelController {
    
        @Autowired
        private LabelService labelService;
    
        /**
         * 查询所有
         * @return
         */
        @RequestMapping(method = RequestMethod.GET)
        public Result findAll() {
            List<Label> labels = labelService.findAll();
            return new Result(true, StatusCode.OK,"查询成功",labels);
        }
    
        /**
         * 根据id查询
         * @param id
         * @return
         */
        @RequestMapping(value = "/{id}",method = RequestMethod.GET)
        public Result findById(@PathVariable("id") String id) {
            Label label = labelService.findById(id);
            return new Result(true, StatusCode.OK,"查询id成功",label);
        }
    
        /**
         * 保存
         * @param label
         * @return
         */
        @RequestMapping(method = RequestMethod.POST)
        public Result save(@RequestBody Label label) {
            labelService.save(label);
            return new Result(true, StatusCode.OK,"保存成功");
        }
    
        /**
         * 更新
         * @param label
         * @return
         */
        @RequestMapping(value = "/{id}",method = RequestMethod.PUT)
        public Result update(@PathVariable("id") String id,@RequestBody Label label) {
            label.setId(id);
            labelService.update(label);
            return new Result(true, StatusCode.OK,"更新成功");
        }
    
        /**
         * 根据id删除
         * @param id
         * @return
         */
        @RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
        public Result delete(@PathVariable("id") String id) {
            labelService.delete(id);
            return new Result(true, StatusCode.OK,"删除成功");
        }
    
    }
    
    
    • @RestController用于json格式的传递
    • @CrossOrigin用于解决跨域调用

2.3 功能测试

  1. 测试查询全部数据
    使用浏览器测试GET方法 http://localhost:9001/label
  2. 测试根据ID查询标签
    使用浏览器测试GET方法 http://localhost:9001/label/1
  3. 测试增加
    使用postMan工具来进行测试POST PUT DELETE等方法。
    在这里插入图片描述
  4. 测试修改
    在这里插入图片描述
  5. 测试删除
    在这里插入图片描述

3.标签管理-条件查询

3.1 标签-条件查询

POST /label/search 根据条件查询标签列表
这里传递的是label对象,也可以使用map,后面方法使用map举例。

  1. 修改LabelController,增加方法findSearch

    	/**
    	 * 条件查询
    	 * @param label
    	 * @return
    	 */
    	@PostMapping("/search")
    	public Result findSearch(@RequestBody Label label) {
    	    List<Label> list = labelService.findSearch(label);
    	    return new Result(true, StatusCode.OK, "查询成功");
    	}
    
  2. 修改LabelService ,增加方法findSearch

    /**
     * 条件查询
     * @return
     */
    public List<Label> findSearch(Label label) {
        // 1.定义条件对象
        Specification<Label> spec = new Specification<Label>() {
            /**
             * 拼装查询条件
             * @param root 根对象,也就是要把条件封装到那个对象中,where 类名=label.getid
             * @param cq 封装的都是查询关键字,比如group by ,order by等
             * @param cb 用来封装条件对象,如果直接返回null,表示不需要任何条件
             * @return
             * 条件是: 标签名称的模糊查询  状态精确查询  是否推荐的精确查询
             */
            @Override
            public Predicate toPredicate(Root<Label> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                ArrayList<Predicate> list = new ArrayList<>();
                // 判断输入了标签名称
                if (!StringUtils.isEmpty(label.getLabelname())) {
                    Predicate p1 = cb.like(root.get("labelname"), label.getLabelname());//想当于 where labelname like '%小明%'
                    list.add(p1);
                }
                // 判断了标签状态
                if (!StringUtils.isEmpty(label.getState())) {
                    Predicate p2 = cb.equal(root.get("state"), label.getState());
                    list.add(p2);
                }
                // 判断了标签的是否推荐
                if (!StringUtils.isEmpty(label.getRecommend())) {
                    Predicate p3 = cb.like(root.get("recommend"), label.getRecommend());
                    list.add(p3);
                }
    
                return cb.and(list.toArray(new Predicate[list.size()]));
            }
        };
        // 2.条件查询
        return labelDao.findAll(spec);
    }
    

    criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
    criteriaBuilder.and()方法需要一个可变参数的数组,用list封装结果后,转成数组。

3.2 带分页的条件查询

使用另外一种写法,传递map对象

  1. 修改LabelController,增加方法pageQuery
     /**
         * 条件+分页查询
         *
         * @param searchMap
         * @param page
         * @param size
         * @return
         */
        @PostMapping(value = "/search/{page}/{size}")
        public Result pageQuery(@RequestBody Map searchMap, @PathVariable int page, @PathVariable int size) {
            Page pageList = labelService.pageQuery(searchMap, page, size);
            return new Result(true, StatusCode.OK, "查询成功", new PageResult<>(pageList.getTotalElements(), pageList.getContent()));
        }
    
    intInteger 的区别,int默认为0,不产生null,但Integer有许多方法可以调用,int没有。
    IDEA快捷键ctrl+H查看实现类
  2. 修改LabelService,增加方法pageQuery
    提取createSpecification()方法,可以公用。
    	/**
     * 构建查询条件
     * @param searchMap
     * @return
     */
    private Specification<Label> createSpecification(Map searchMap) {
        return new Specification<Label>() {
            @Override
            public Predicate toPredicate(Root<Label> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                List<Predicate> predicateList = new ArrayList<>();
                if (!StringUtils.isEmpty(searchMap.get("labelname"))) {
                    predicateList.add(cb.like(root.get("labelname").as(String.class), "%" + (String) searchMap.get("labelname") + "%"));
                }
                if (!StringUtils.isEmpty(searchMap.get("state"))) {
                    predicateList.add(cb.equal(root.get("state").as(String.class), (String) searchMap.get("state")));
                }
                if (!StringUtils.isEmpty(searchMap.get("recommend"))) {
                    predicateList.add(cb.equal(root.get("recommend").as(String.class), (String) searchMap.get("recommend")));
                }
                return cb.and(predicateList.toArray(new Predicate[predicateList.size()]));
            }
        };
    }
    
    service的分页条件查询pageQuery方法
    /**
     * 分页条件查询
     * @param searchMap
     * @param page
     * @param size
     * @return
     */
    public Page<Label> pageQuery(Map searchMap, int page, int size) {
        // 1.定义条件对象
        Specification specification = createSpecification(searchMap);
        Pageable pageable = PageRequest.of(page - 1, size);
        // 2.条件查询
        return labelDao.findAll(specification, pageable);
    }
    

3.3 测试

4. 公共异常处理

为了使我们的代码更容易维护,我们创建一个类集中处理异常
在om.tensquare.user.controller包下创建公共异常处理类BaseExceptionHandler

package com.tensquare.base;
/**
 * 统一异常处理类
 */
@RestControllerAdvice
public class BaseExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    public Result error(Exception e) {
        e.printStackTrace();
        return new Result(false, StatusCode.ERROR, e.getMessage());
    }

}

十次方00、目录
https://blog.youkuaiyun.com/amingccc/article/details/84260613

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值