一 微服务项目搭建

一 项目介绍

项目整体架构
一 微服务项目搭建_第1张图片

技术架构
一 微服务项目搭建_第2张图片

项目结构
一 微服务项目搭建_第3张图片
结构说明:

changgou_gateway
网关模块,根据网站的规模和需要,可以将综合逻辑相关的服务用网关路由组合到一起。在这里还可以做鉴权和限流相关操作。

changgou_service
微服务模块,该模块用于存放所有独立的微服务工程。

changgou_service_api
对应工程的JavaBean、Feign、以及Hystrix配置,该工程主要对外提供依赖。

changgou_transaction_fescar
分布式事务模块,将分布式事务抽取到该工程中,任何工程如需要使用分布式事务,只需依赖该工程即可。

changgou_web
web服务工程,对应功能模块如需要调用多个微服务,可以将他们写入到该模块中,例如网站后台、网站前台等

二 框架搭建

2.1 父工程搭建

2.1.1 一级父工程搭建

从上边可以看出来,有很多微服务项目,所有我们需要为这些微服务搭建一个父工程;创建父工程 changgou_parent ,pom.xml文件中增加配置


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.changgougroupId>
    <artifactId>changgou_parentartifactId>
    <packaging>pompackaging>
    <version>1.0-SNAPSHOTversion>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.1.4.RELEASEversion>
    parent>

    <properties>
        <skipTests>trueskipTests>
    properties>

    
    <dependencies>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>Greenwich.SR1version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>
project>

删除父工程里的src文件夹(因为是父工程,不写代码,只提供依赖,所以删除src目录)

2.1.2 二级父工程模块搭建

创建changgou_gateway、changgou_service、changgou_service_api、changgou_web工程,工程全部为pom工程,同样,将所有工程的src文件删除。

2.2 Eureka微服务搭建

创建模块changgou_eureka

2.2.1 pom.xml引入依赖


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>changgou_parentartifactId>
        <groupId>com.changgougroupId>
        <version>1.0-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>
    <artifactId>changgou_eurekaartifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
        dependency>
    dependencies>
project>

2.2.2 appliation.yml配置

server:
  port: 6868
eureka:
  client:
    register-with-eureka: false #是否将自己注册到eureka中
    fetch-registry: false #是否从eureka中获取信息
    service-url:
      defaultZone: http://127.0.0.1:${
     server.port}/eureka/

2.2.3 启动类配置

创建包com.changgou.eureka 包下创建启动类

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
     
    public static void main(String[] args) {
     
        SpringApplication.run(EurekaApplication.class);
    }
}

2.3 公共模块搭建

2.3.1 全局公共模块

  1. 创建公共子模块changgou_common,pom.xml引入依赖

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>changgou_parentartifactId>
        <groupId>com.changgougroupId>
        <version>1.0-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>
    <artifactId>changgou_commonartifactId>
    <dependencies>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>fastjsonartifactId>
            <version>1.2.51version>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
        dependency>
    dependencies>
project>

公共子模块引入这些依赖后,其他微服务引入changgou_common后也自动引入了这些依赖

  1. 常用对象
    创建com.changgou.entity包 ,包下建立类Result用于微服务返回结果给前端
/**
 * 返回结果实体类
 */
public class Result {
     

    private boolean flag;//是否成功
    private Integer code;//返回码
    private String message;//返回消息

    private Object data;//返回数据

    public Result(boolean flag, Integer code, String message, Object data) {
     
        this.flag = flag;
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public Result(boolean flag, Integer code, String message) {
     
        this.flag = flag;
        this.code = code;
        this.message = message;
    }

    public Result() {
     
        this.flag = true;
        this.code = StatusCode.OK;
        this.message = "执行成功";
    }

    // getter and setter.....
}

建立类用于承载分页的数据结果(该项目不使用这个分页,只做了解)

/**
 * 分页结果类
 */
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() {
     
    
    }

    //getter and setter ......
}

创建返回状态码实体类

/**
 * 返回码
 */
public class StatusCode {
     

    public static final int OK=20000;//成功
    public static final int ERROR =20001;//失败
    public static final int LOGINERROR =20002;//用户名或密码错误
    public static final int ACCESSERROR =20003;//权限不足
    public static final int REMOTEERROR =20004;//远程调用失败
    public static final int REPERROR =20005;//重复操作
}
  1. 生成id工具类(推特的工具,每秒可以生成26万个不重复的ID)
package com.changgou.util;

import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;

/**
 * 

名称:IdWorker.java

*

描述:分布式自增长ID

*
 *     Twitter的 Snowflake JAVA实现方案  每秒可以生成26万个不重复的ID
 * 
* 核心代码为其IdWorker这个类实现,其原理结构如下,我分别用一个0表示一位,用—分割开部分的作用: * 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000 * 在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间, * 然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识), * 然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。 * 这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分), * 并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。 *

* 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加)) * * @author Polim */ public class IdWorker { // 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动) private final static long twepoch = 1288834974657L; // 机器标识位数 private final static long workerIdBits = 5L; // 数据中心标识位数 private final static long datacenterIdBits = 5L; // 机器ID最大值 private final static long maxWorkerId = -1L ^ (-1L << workerIdBits); // 数据中心ID最大值 private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); // 毫秒内自增位 private final static long sequenceBits = 12L; // 机器ID偏左移12位 private final static long workerIdShift = sequenceBits; // 数据中心ID左移17位 private final static long datacenterIdShift = sequenceBits + workerIdBits; // 时间毫秒左移22位 private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; private final static long sequenceMask = -1L ^ (-1L << sequenceBits); /* 上次生产id时间戳 */ private static long lastTimestamp = -1L; // 0,并发控制 private long sequence = 0L; private final long workerId; // 数据标识id部分 private final long datacenterId; public IdWorker(){ this.datacenterId = getDatacenterId(maxDatacenterId); this.workerId = getMaxWorkerId(datacenterId, maxWorkerId); } /** * @param workerId * 工作机器ID * @param datacenterId * 序列号 */ 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; } /** * 获取下一个ID * * @return */ 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) { // 当前毫秒内,则+1 sequence = (sequence + 1) & sequenceMask; if (sequence == 0) { // 当前毫秒内计数满了,则等待下一秒 timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L; } lastTimestamp = timestamp; // ID偏移组合生成最终的ID,并返回ID 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(); } /** *

* 获取 maxWorkerId *

*/
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) { StringBuffer mpid = new StringBuffer(); mpid.append(datacenterId); String name = ManagementFactory.getRuntimeMXBean().getName(); if (!name.isEmpty()) { /* * GET jvmPid */ mpid.append(name.split("@")[0]); } /* * MAC + PID 的 hashcode 获取16个低位 */ return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1); } /** *

* 数据标识id部分 *

*/
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; } public static void main(String[] args) { IdWorker idWorker=new IdWorker(0,0); for(int i=0;i<10000;i++){ long nextId = idWorker.nextId(); System.out.println(nextId); } } }

2.3.2 数据访问层公共模块搭建

创建公共模块changgou_common_db ,删除src文件夹,pom文件引入依赖


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>changgou_parentartifactId>
        <groupId>com.changgougroupId>
        <version>1.0-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>

    <artifactId>changgou_common_dbartifactId>
    <dependencies>
        <dependency>
            <groupId>com.changgougroupId>
            <artifactId>changgou_commonartifactId>
            <version>1.0-SNAPSHOTversion>
        dependency>
        
        <dependency>
            <groupId>tk.mybatisgroupId>
            <artifactId>mapper-spring-boot-starterartifactId>
            <version>2.0.4version>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>
        
        <dependency>
            <groupId>com.github.pagehelpergroupId>
            <artifactId>pagehelper-spring-boot-starterartifactId>
            <version>1.2.3version>
        dependency>
    dependencies>
project>

这个公共模块是连接mysql数据库的公共微服务模块,所以需要连接mysql的微服务都继承自此工程。

2.4 商品微服务搭建

2.4.1 商品微服务API工程搭建

  1. changgou_service_api 引入依赖
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-openfeign</artifactId>
     <scope>provided</scope>
</dependency>
<dependency>
     <groupId>javax.persistence</groupId>
     <artifactId>persistence-api</artifactId>
     <version>1.0</version>
     <scope>compile</scope>
</dependency>
  1. changgou_service_api 下创建changgou_service_goods_api 子模块

2.4.2 Service层微服务工程搭建

  1. changgou_service下创建changgou_service_goods子模块 ,pom.xml引入依赖

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>changgou_serviceartifactId>
        <groupId>com.changgougroupId>
        <version>1.0-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>
    <artifactId>changgou_service_goodsartifactId>

    <dependencies>
        <dependency>
            <groupId>com.changgougroupId>
            <artifactId>changgou_common_dbartifactId>
            <version>1.0-SNAPSHOTversion>
        dependency>
		<dependency>
            <groupId>com.changgougroupId>
            <artifactId>changgou_service_goods_apiartifactId>
            <version>1.0-SNAPSHOTversion>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
     dependencies>
project>
  1. 创建配置文件application.yml
server:
  port: 9011
spring:
  application:
    name: goods
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.200.128:3306/changgou_goods?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: root
    password: admin
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka
  instance:
    prefer-ip-address: true
feign:
  hystrix:
    enabled: true
    
#hystrix 配置
hystrix:
  command:
    default:
      execution:
        timeout:
        #如果enabled设置为false,则请求超时交给ribbon控制
          enabled: true
        isolation:
          strategy: SEMAPHORE
# 由于使用MyBatis通用Mapper,实现了0sql,所以这里不写MyBatis配置了
  1. 创建包com.changgou 包下创建启动类
@SpringBootApplication
//开启Eureka客户端
@EnableEurekaClient
//开启通用Mapper包扫描,注意导入的包是tk下的包
@MapperScan(basePackages = {
     "com.changgou.goods.dao"})
public class GoodsApplication {
     
    public static void main(String[] args) {
     
        SpringApplication.run(GoodsApplication.class);
    }
}

三 商品微服务-品牌增删改查

3.1 需求分析

创建商品微服务,实现对品牌表的增删改查功能。具体包括

(1)查询全部列表数据

(2)根据ID查询实体数据

(3)增加

(4)修改

(5)删除

(6)条件查询

(7)分页查询

(8)分页+条件查询

(9)公共异常处理

3.2 表结构分析

字段名称 字段含义 字段类型 字段长度 备注
id 品牌id INT
name 品牌名称 VARCHAR
image 品牌图片地址 VARCHAR
letter 品牌的首字母 CHAR
seq 排序 INT

3.3 代码实现

3.3.1 品牌列表

  1. (1)在changgou_service_goods_api创建com.changgou.pojo包,包下创建Brand实体类
@Table(name="tb_brand")
public class Brand implements Serializable{
     
	@Id
	private Integer id;//品牌id
	private String name;//品牌名称
	private String image;//品牌图片地址
	private String letter;//品牌的首字母
	private Integer seq;//排序
	
	// getter and setter  .....(省略)
}

@Table和@Id都是JPA注解,@Table用于配置表与实体类的映射关系,@Id用于标识主键属性。

  1. Dao创建
    在changgou_service_goods微服务下创建com.changgou.goods.dao.BrandMapper接口,代码如下:
public interface BrandMapper extends Mapper<Brand> {
     
}

使用通用Mapper,不需要写sql语句;继承了Mapper接口,就自动实现了增删改查的常用方法,注意,Mapper接口导入的包是tk下的包(记的在启动类上加@MapperScan注解)
一 微服务项目搭建_第4张图片

  1. 业务层
    创建com.changgou.goods.service.BrandService接口,代码如下:
public interface BrandService {
     

    /***
     * 查询所有品牌
     * @return
     */
  public  List<Brand> findAll();
}

创建com.changgou.goods.service.impl包,包下创建服务实现类 BrandServiceImpl,代码如下:

@Service
public class BrandServiceImpl implements BrandService {
     
    
    @Autowired
    private BrandMapper brandMapper;
    
    @Override
    public List<Brand> findAll() {
     
        return brandMapper.selectAll();
    }   
}
  1. 控制层

控制层 com.changgou.goods包下创建controller包 ,包下创建类

@RestController
@RequestMapping("/brand")
/**
*跨域:A域名访问B域名的数据
*  域名或者请求端口或者协议不一致的时候,就是跨域了
*  域名不一致:www.baidu.com下的html,访问www.souhu.com下的任何资源
*  协议不一样:https://www.baidu.com 访问 http://www.baidu.com
*  端口不一样:www.baidu.com:8081 访问 www.baidu.com:8082
*  如果不加这个注解的话,跨域是访问不了的
**/
@CrossOrigin
public class BrandController {
     

    @Autowired
    private BrandService brandService;

    @GetMapping
    public Result findAll(){
     
        List<Brand> brandList = brandService.findAll();
        return new Result(true, StatusCode.OK,"查询成功",brandList) ;
    }
}

3.3.2 根据ID查询品牌

  1. 业务层接口

修改com.changgou.goods.service.BrandService接口,添加根据ID查询品牌数据方法,代码如下:

/**
 * 根据ID查询
 * @param id
 * @return
 */
public Brand findById(Integer id);
  1. 业务层实现
    修改com.changgou.goods.service.impl.BrandServiceImpl新增方法,代码如下:
/**
 * 根据ID查询
 * @param id
 * @return
 */
@Override
public Brand findById(Integer id){
     
    return  brandMapper.selectByPrimaryKey(id);
}
  1. 控制层
    BrandController新增方法
/***
 * 根据ID查询品牌数据
 * @param id
 * @return
 */
@GetMapping("/{id}")
public Result findById(@PathVariable Integer id){
     
    Brand brand = brandService.findById(id);
    return new Result(true,StatusCode.OK,"查询成功",brand);
}

3.3.3 新增品牌

  1. 业务层接口 修改com.changgou.goods.service.BrandService,新增方法
/***
 * 新增品牌
 * @param brand
 */
public void add(Brand brand);
  1. 业务层实现 修改com.changgou.goods.service.impl.BrandServiceImpl,新增增加品牌方法代码如下:
/**
 * 增加
 * @param brand
 */
@Override
public void add(Brand brand){
     
   //注意:使用insertSelective方法,不使用insert方法,因为insertSelective会忽略实体类里的空值属性(哪些属性有值就插入哪些属性值),而insert会将没有值的属性置为null后插入数据库里
    brandMapper.insertSelective(brand);
}
  1. 控制层 BrandController新增方法
/***
 * 新增品牌数据
 * @param brand
 * @return
 */
@PostMapping
public Result add(@RequestBody Brand brand){
     
    brandService.add(brand);
    return new Result(true,StatusCode.OK,"添加成功");
}

3.3.4 修改品牌

  1. 业务层接口
    需改com.changgou.goods.service.BrandService,添加修改品牌方法,代码如下:
/***
 * 修改品牌数据
 * @param brand
 */
public void update(Brand brand);
  1. 业务层实现 修改com.changgou.goods.service.impl.BrandServiceImpl,添加修改品牌方法,代码如下:
/**
 * 修改
 * @param brand
 */
@Override
public void update(Brand brand){
     
    brandMapper.updateByPrimaryKeySelective(brand);
}
  1. 控制层
    BrandController新增方法
/***
 * 修改品牌数据
 * @param brand
 * @param id
 * @return
 */
@PutMapping(value="/{id}")
public Result update(@RequestBody Brand brand,@PathVariable Integer id){
     
    brand.setId(id);
    brandService.update(brand);
    return new Result(true,StatusCode.OK,"修改成功");
}

3.3.5 删除品牌

  1. 业务层接口
    修改com.changgou.goods.service.BrandService,添加删除品牌方法,代码如下:
/***
 * 删除品牌
 * @param id
 */
public void delete(Integer id);
  1. 业务层实现 修改com.changgou.goods.service.impl.BrandServiceImpl,新增删除品牌方法,代码如下:
/**
 * 删除
 * @param id
 */
@Override
public void delete(Integer id){
     
    brandMapper.deleteByPrimaryKey(id);
}
  1. 控制层 BrandController新增方法
/***
 * 根据ID删除品牌数据
 * @param id
 * @return
 */
@DeleteMapping(value = "/{id}" )
public Result delete(@PathVariable Integer id){
     
    brandService.delete(id);
    return new Result(true,StatusCode.OK,"删除成功");
}

3.3.6 品牌列表条件查询

  1. 业务层接口
    修改com.changgou.goods.service.BrandService,增加根据条件搜索品牌方法,代码如下:
/***
 * 多条件搜索品牌方法
 * @param searchMap
 * @return
 */
public List<Brand> findList(Map<String, Object> searchMap);
  1. 业务层实现
    修改com.changgou.goods.service.impl.BrandServiceImpl,添加根据多条件搜索品牌方法的实现,代码如下:
/**
 * 条件查询
 * @param searchMap
 * @return
 */
@Override
public List<Brand> findList(Map<String, Object> searchMap){
     
	Example example = createExample(searchMap);
	return brandMapper.selectByExample(example);
}

/**
 * 构建查询对象
 * @param searchMap
 * @return
 */
private Example createExample(Map<String, Object> searchMap){
     
	Example example=new Example(Brand.class);
	//条件构造器
	Example.Criteria criteria = example.createCriteria();
	if(searchMap!=null){
     
		// 品牌名称
		if(searchMap.get("name")!=null && !"".equals(searchMap.get("name"))){
     
			criteria.andLike("name","%"+searchMap.get("name")+"%");
		}
		// 品牌的首字母
		if(searchMap.get("letter")!=null && !"".equals(searchMap.get("letter"))){
     
			criteria.andEqualTo("letter",searchMap.get("letter"));
		}
	}
	return example;
}
  1. 控制层 BrandController新增方法
/***
 * 多条件搜索品牌数据
 * @param searchMap
 * @return
 */
@GetMapping(value = "/search" )
public Result findList(@RequestParam Map searchMap){
     
	List<Brand> list = brandService.findList(searchMap);
	return new Result(true,StatusCode.OK,"查询成功",list);
}

3.3.7 品牌列表分页查询

  1. 业务层接口
    修改com.changgou.goods.service.BrandService添加分页方法,代码如下:
/***
 * 分页查询
 * @param page 当前页
 * @param size 每页显示的条数
 * @return
 */
public PageInfo<Brand> findPage(int page, int size);
  1. 业务层实现
    修改com.changgou.goods.service.impl.BrandServiceImpl添加分页方法实现,代码如下:
@Override
public PageInfo<Brand> findPage(int page, int size){
     
   PageHelper.startPage(page,size);
   //由于上边使用了PageHelper分页,所以下边必须是一个集合类型的数
   List<Brand> brands = brandMapper.selectAll();
   return  new PageInfo<Brand>(brands);
}
  1. 控制层 BrandController新增方法
/***
 * 分页搜索实现
 * @param searchMap
 * @param page
 * @param size
 * @return
 */
@GetMapping(value = "/search/{page}/{size}" )
public Result findPage(@PathVariable  int page, @PathVariable  int size){
     
	PageInfo<Brand> pageList = brandService.findPage( page, size);
      
    return new Result<PageInfo<Brand>>(true,StatusCode.OK,"分页查询成功",pageList);
}

其中,PageResult如下

package com.changgou.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() {
     
    }

    public Long getTotal() {
     
        return total;
    }

    public void setTotal(Long total) {
     
        this.total = total;
    }

    public List<T> getRows() {
     
        return rows;
    }

    public void setRows(List<T> rows) {
     
        this.rows = rows;
    }
}

3.3.8 品牌列表条件+分页查询

  1. 业务层接口
    修改com.changgou.goods.service.BrandService,增加多条件分页查询方法,代码如下:
/***
 * 多条件分页查询
 * @param searchMap
 * @param page
 * @param size
 * @return
 */
Page<Brand> findPage(Map<String, Object> searchMap, int page, int size);
  1. 业务层实现
    修改com.changgou.goods.service.impl.BrandServiceImpl,添加多条件分页查询方法代码如下:
/**
 * 条件+分页查询
 * @param searchMap 查询条件
 * @param page 页码
 * @param size 页大小
 * @return 分页结果
 */
@Override
public Page<Brand> findPage(Map<String,Object> searchMap, int page, int size){
     
    PageHelper.startPage(page,size);
    Example example = createExample(searchMap);
    return (Page<Brand>)brandMapper.selectByExample(example);
}
  1. 控制层
    BrandController新增方法
/***
 * 分页搜索实现
 * @param searchMap
 * @param page
 * @param size
 * @return
 */
@PostMapping(value = "/search/{page}/{size}" )
public Result findPage(@RequestParam Map searchMap, @PathVariable  int page, @PathVariable  int size){
     
	Page<Brand> pageList = brandService.findPage(searchMap, page, size);
	PageResult pageResult=new PageResult(pageList.getTotal(),pageList.getResult());
	return new Result(true,StatusCode.OK,"查询成功",pageResult);
}

3.3.9 公共异常处理

为了使我们的代码更容易维护,我们创建一个类集中处理异常

在com.changgou.goods.controller包下创建公共异常处理类BaseExceptionHandler

/**
 * 统一异常处理类
 */
@ControllerAdvice
public class BaseExceptionHandler {
     
	
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result error( Exception e) {
     
        e.printStackTrace();        
        return new Result(false, StatusCode.ERROR, e.getMessage());
    }
}

此时,controller层报错的时候,就会返回json格式的错误信息数据给前台;

你可能感兴趣的:(笔记)