环境配置
本篇文章按照微服务架构搭建,主要实现为JPA增删改查,条件查询,分页查询等功能,及常规返回值,分页返回值,状态码返回值对象的设计思想综合案例
1. SpringBoot配置
pom.xml 文件中添加依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
resources/application.yml 配置参数
server:
port: 9001
spring:
application:
name: tensquare-base
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/tensquare_base?useUnicode=true&characterEncoding=utf-8&useSSL=false
jpa:
database: MySQL
show‐sql: true
generate‐ddl: true
2. 实体类配置
Label实体类 数据库建表语句,复制粘贴执行即可
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `tb_label`;
CREATE TABLE `tb_label` (
`id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '标签ID',
`labelname` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '标签名称',
`state` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '状态',
`count` bigint(20) NULL DEFAULT NULL COMMENT '使用数量',
`recommend` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否推荐',
`fans` bigint(20) NULL DEFAULT NULL COMMENT '粉丝数',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '标签' ROW_FORMAT = Dynamic;
INSERT INTO `tb_label` VALUES ('1519209207952445440', 'PHP', '1', 5443, '1', 123);
INSERT INTO `tb_label` VALUES ('1519216642389839872', 'Centos', '1', 6554, '1', 888);
INSERT INTO `tb_label` VALUES ('1519216690687250432', 'Java', '1', 23444, '0', 2324);
INSERT INTO `tb_label` VALUES ('1519217313897910272', 'JavaScript', '1', 23444, '0', 198);
SET FOREIGN_KEY_CHECKS = 1;
pojo/Label 对象实体类
package com.tensquare.base.pojo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
@Entity
@Table(name="tb_label")
public class Label implements Serializable{
@Id
private String id;
private String labelname;
private String state;
private Long count;
private String recommend;
private Long fans;
......GET AND SET 自己添加即可
}
entity/Result 返回值对象
package entity;
public class Result {
private Boolean flag;
private Integer code;
private String message;
private Object data;
public Result(Boolean flag, Integer code, String message) {
this.flag = flag;
this.code = code;
this.message = message;
}
public Result(Boolean flag, Integer code, String message, Object data) {
this.flag = flag;
this.code = code;
this.message = message;
this.data = data;
}
public Result() {
}
......GET AND SET 自己添加即可
}
entity/PageResult 分页返回值对象
package entity;
import java.util.List;
public class PageResult<T> {
private Long total;
private List<T> rows;
public PageResult(Long total, List<T> rows) {
this.total = total;
this.rows = rows;
}
public PageResult() {
}
......GET AND SET 自己添加即可
}
utils/IdWorker 雪花ID工具类
package utils;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
public class IdWorker {
private final static long twepoch = 1288834974657L;
private final static long workerIdBits = 5L;
private final static long datacenterIdBits = 5L;
private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
private final static long sequenceBits = 12L;
private final static long workerIdShift = sequenceBits;
private final static long datacenterIdShift = sequenceBits + workerIdBits;
private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
private static long lastTimestamp = -1L;
private long sequence = 0L;
private final long workerId;
private final long datacenterId;
public IdWorker(){
this.datacenterId = getDatacenterId(maxDatacenterId);
this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
}
public IdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
public synchronized long nextId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
long nextId = ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift) | sequence;
return nextId;
}
private long tilNextMillis(final long lastTimestamp) {
long timestamp = this.timeGen();
while (timestamp <= lastTimestamp) {
timestamp = this.timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
StringBuffer mpid = new StringBuffer();
mpid.append(datacenterId);
String name = ManagementFactory.getRuntimeMXBean().getName();
if (!name.isEmpty()) {
mpid.append(name.split("@")[0]);
}
return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
}
protected static long getDatacenterId(long maxDatacenterId) {
long id = 0L;
try {
InetAddress ip = InetAddress.getLocalHost();
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
if (network == null) {
id = 1L;
} else {
byte[] mac = network.getHardwareAddress();
id = ((0x000000FF & (long) mac[mac.length - 1])
| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
id = id % (maxDatacenterId + 1);
}
} catch (Exception e) {
System.out.println(" getDatacenterId: " + e.getMessage());
}
return id;
}
}
3. BaseApplication配置
注入雪花ID工具类
package com.tensquare.base;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import utils.IdWorker;
@SpringBootApplication
public class BaseApplication {
public static void main(String[] args) {
SpringApplication.run(BaseApplication.class);
}
@Bean
public IdWorker idWorker() {
return new IdWorker(1, 1);
}
}
4. 代码实现
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> {
}
service/LabelService 代码
package com.tensquare.base.service;
import com.tensquare.base.dao.LabelDao;
import com.tensquare.base.pojo.Label;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import utils.IdWorker;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
@Transactional
public class LabelService {
@Autowired
private LabelDao labelDao;
@Autowired
private IdWorker idWorker;
public Page<Label> search(Map map, int page, int size) {
Specification spec = CreatSpecification(map);
Pageable pageable = PageRequest.of(page - 1, size);
return labelDao.findAll(spec, pageable);
}
public List<Label> search(Map map) {
Specification spec = CreatSpecification(map);
return labelDao.findAll(spec);
}
private Specification CreatSpecification(Map map) {
Specification spec = new Specification() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery cq, CriteriaBuilder cb) {
List<Predicate> predicateList = new ArrayList<>();
if (map.get("labelname") != null && !"".equals(map.get("labelname"))) {
Predicate p1 = cb.like(root.get("labelname").as(String.class), "%" + map.get("labelname") + "%");
predicateList.add(p1);
}
if (map.get("state") != null && !"".equals(map.get("state"))) {
Predicate p2 = cb.equal(root.get("state").as(String.class), map.get("state") + "");
predicateList.add(p2);
}
if (map.get("recommend") != null && !"".equals(map.get("recommend"))) {
Predicate p3 = cb.equal(root.get("recommend").as(String.class), map.get("recommend") + "");
predicateList.add(p3);
}
Predicate p4 = cb.and(predicateList.toArray(new Predicate[predicateList.size()]));
return p4;
}
};
return spec;
}
public List<Label> findAll() {
return labelDao.findAll();
}
public Label findById(String id) {
return labelDao.findById(id).get();
}
public void save(Label label) {
label.setId(idWorker.nextId() + "");
labelDao.save(label);
}
public void update(Label label) {
labelDao.save(label);
}
public void deleteById(String id) {
labelDao.deleteById(id);
}
}
controller/LabelController 代码
package com.tensquare.base.controller;
import com.tensquare.base.pojo.Label;
import com.tensquare.base.service.LabelService;
import entity.PageResult;
import entity.Result;
import entity.StatusCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/label")
public class LabelController {
@Autowired
private LabelService labelService;
@RequestMapping(value = "/search/{page}/{size}", method = RequestMethod.POST)
public Result search(@RequestBody Map map, @PathVariable int page, @PathVariable int size) {
Page<Label> page1 = labelService.search(map, page, size);
return new Result(true, StatusCode.OK, "查询成功", new PageResult(page1.getTotalElements(), page1.getContent()));
}
@RequestMapping(value = "/search", method = RequestMethod.POST)
public Result search(@RequestBody Map map) {
List<Label> search = labelService.search(map);
return new Result(true, StatusCode.OK, "查询成功", search);
}
@RequestMapping(method = RequestMethod.GET)
public Result findAll() {
List<Label> list = labelService.findAll();
return new Result(true, StatusCode.OK, "查询成功", list);
}
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Result findById(@PathVariable String id) {
Label label = labelService.findById(id);
return new Result(true, StatusCode.OK, "查询成功", label);
}
@RequestMapping(method = RequestMethod.POST)
public Result save(@RequestBody Label label) {
labelService.save(label);
return new Result(true, StatusCode.OK, "添加成功");
}
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public Result update(@PathVariable String id, @RequestBody Label label) {
label.setId(id);
labelService.update(label);
return new Result(true, StatusCode.OK, "修改成功");
}
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public Result deleteById(@PathVariable String id) {
labelService.deleteById(id);
return new Result(true, StatusCode.OK, "删除成功");
}
}
5. 使用Postman测试
注意这里所有的请求都是RestFul风格,为了方便只展示几种结果,其余的自己测试即可
5.1 查询所有
localhost:9001/label ,请求方式为 GET
5.2 添加数据
请求地址: localhost:9001/label ,请求方式为 POST
json数据
{
"labelname":"JavaScript",
"state":"1",
"count":"23444",
"recommend":"1",
"fans":"198"
}
5.3 修改数据
请求地址 : localhost:9001/label/加上ID ,请求方式 PUT json数据自己改改就行
5.4 条件查询
请求地址 : localhost:9001/label/search ,请求方式 POST 由于代码里只判断了labelname,state,recommend 三个参数,所以我们只在这三个参数中选择就行
json数据
{
"labelname":"java",
"recommend":"0"
}
5.5 带条件的分页查询
请求地址: localhost:9001/label/search/第几页/每页显示几条 ,请求方式为 POST
|