文章目录
基础微服务-标签功能
1. 模块搭建tensquare_base
- 搭建基础微服务模块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>
- 创建启动类
提示:IDEA创建main方法的快捷键是 psvmpackage 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); } }
- 在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 表结构分析
- 表名称:tb_label
字段名称 字段含义 字段类型 备注 id ID 文本 labelname 标签名称 文本 state 状态 文本 0:无效 1:有效 count 使用数量 整型 fans 关注数 整型 recommend 是否推荐 文本 0:不推荐 1:推荐 - 建数据库:
/*!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`;
- 建表语句:
/*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的实现
-
实体类
创建com.tensquare.base包,包下创建pojo包 ,包下创建实体类Labelpackage 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; } }
-
创建数据访问接口
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用于做复杂的条件查询 -
业务逻辑类
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); } }
-
控制器类
com.tensquare.user包下创建controller包,创建UserControllerpackage 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 功能测试
- 测试查询全部数据
使用浏览器测试GET方法 http://localhost:9001/label - 测试根据ID查询标签
使用浏览器测试GET方法 http://localhost:9001/label/1 - 测试增加
使用postMan工具来进行测试POST PUT DELETE等方法。
- 测试修改
- 测试删除
3.标签管理-条件查询
3.1 标签-条件查询
POST /label/search 根据条件查询标签列表
这里传递的是label对象,也可以使用map,后面方法使用map举例。
-
修改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, "查询成功"); }
-
修改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对象
- 修改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())); }
int
和Integer
的区别,int默认为0,不产生null,但Integer有许多方法可以调用,int没有。
IDEA快捷键ctrl+H
查看实现类 - 修改LabelService,增加方法pageQuery
提取createSpecification()
方法,可以公用。
service的分页条件查询pageQuery方法/** * 构建查询条件 * @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()])); } }; }
/** * 分页条件查询 * @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 测试
- 不带分页的条件查询,http://localhost:9001/label/search
- 带条件的分页查询,http://localhost:9001/label/search/1/10
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