查看原文
其他

Spring全家桶系列--SpringBoot渐入佳境

cuifuan Java知音 2019-06-23

//本文作者:cuifuan

//本文将收录到菜单栏:《Spring全家桶》专栏中

如果要想加入spring交流群,可以点这里:spring交流群

萌新:小哥,我在实体类写了那么多get/set方法,看着很迷茫

小哥:那不是可以自动生成吗?
萌新:虽然可以自动生成,但是如果我要修改某个变量的数据类型,我岂不是还要去修改get/set方法?
小哥:哈哈,那我今天给你说一个插件,lombok可以解决你的问题

1.Lombok插件

对于开发人员来说,我要解释这个什么意思,你肯定也是一知半解,直接来代码解释吧

1.1 代码演示

  1. package com.example.entity;

  2. public class Area {

  3.    private Integer id;

  4.    private Integer postalcode;

  5.    private String address;

  6.    private Integer type;

  7.    public Integer getId() {

  8.        return id;

  9.    }

  10.    public void setId(Integer id) {

  11.        this.id = id;

  12.    }

  13.    public Integer getPostalcode() {

  14.        return postalcode;

  15.    }

  16.    public void setPostalcode(Integer postalcode) {

  17.        this.postalcode = postalcode;

  18.    }

  19.    public String getAddress() {

  20.        return address;

  21.    }

  22.    public void setAddress(String address) {

  23.        this.address = address == null ? null : address.trim();

  24.    }

  25.    public Integer getType() {

  26.        return type;

  27.    }

  28.    public void setType(Integer type) {

  29.        this.type = type;

  30.    }

  31. }

使用了Lombok之后

  1. package com.example.entity;

  2. import lombok.Data;

  3. @Data

  4. public class Area {

  5.    private Integer id;

  6.    private Integer postalcode;

  7.    private String address;

  8.    private Integer type;

  9. }

以上两者的效果是相同的,现在我们知道它是干嘛的了,下面开始使用吧

1.2 安装Lombok

在Intellij IDEA中安装lombok插件

安装完重启IDEA

打开设置找到上述并勾选,然后在build.gradle文件中增加

  1. //让gradle具有内置的compileOnly范围,可用于告诉gradle仅在编译期间添加lombok

  2. compileOnly 'org.projectlombok:lombok:1.18.4'


刷新Gradle之后就可以了

然后随意找个测试类,例如如下

  1. package com.example.demo;

  2. import com.example.entity.Area;

  3. import org.junit.Test;

  4. import org.junit.runner.RunWith;

  5. import org.springframework.boot.test.context.SpringBootTest;

  6. import org.springframework.test.context.junit4.SpringRunner;

  7. @RunWith(SpringRunner.class)

  8. @SpringBootTest

  9. public class DemoApplicationTests {

  10.    @Test

  11.    public void contextLoads() {

  12.        Area area=new Area();

  13.        //这里可以有get方法证明就ok 可以使用了

  14.        area.getType();

  15.    }

  16. }

2.PageHelper分页插件

萌新:小哥,我很苦恼分页这个功能怎么办?
小哥:那不是可以写好一个逻辑直接复制吗?
萌新:那也需要很多行代码,导致了需要在mapper以及业务层做很多无用功
小哥:哈哈,那我来告诉你一款分页插件,解决你的困扰

首先,在build.gradle中引入依赖

  1. /** buildscript中的声明是gradle脚本自身需要使用的资源。

  2. *  可以声明的资源包括依赖项、第三方插件、maven仓库地址等

  3. */

  4. buildscript {

  5.    ext {

  6.        springBootVersion = '2.0.1.RELEASE'

  7.        mysqlVersion = '5.1.39'

  8.    }

  9.    repositories {

  10.        //使用国内源下载依赖

  11.        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }

  12.    }

  13.    dependencies {

  14.        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")

  15.    }

  16. }

  17. // 应用Java插件

  18. apply plugin: 'java'

  19. //让工程支持IDEA的导入

  20. apply plugin: 'idea'

  21. apply plugin: 'org.springframework.boot'

  22. group = 'com.example'

  23. version = '0.0.1-SNAPSHOT'

  24. sourceCompatibility = 1.8

  25. //build.gradle文件中直接声明的依赖项、仓库地址等信息是项目自身需要的资源。

  26. repositories {

  27.    maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }

  28.    mavenCentral()

  29. }

  30. /**

  31. * 在gradle里,对依赖的定义有6种

  32. * compile, runtime, testCompile, testRuntime, providedCompile,providedRuntime

  33. * compile:需要引用这个库才能进行编译工作

  34. * testRuntime : 测试依赖范围

  35. * 其他的了解:http://shmilyaw-hotmail-com.iteye.com/blog/2345439

  36. */

  37. dependencies {

  38.    compile('org.springframework.boot:spring-boot-starter-web:2.0.1.RELEASE')

  39.    compile('com.alibaba:druid:1.0.29')

  40.    testCompile('org.springframework.boot:spring-boot-starter-test:2.0.1.RELEASE')

  41.    //这里的版本可以在上述定义

  42.    compile 'mysql:mysql-connector-java:5.1.39'

  43.    compile 'org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2'

  44.    //让gradle具有内置的compileOnly范围,可用于告诉gradle仅在编译期间添加lombok

  45.    compileOnly 'org.projectlombok:lombok:1.18.4'

  46.    //分页插件

  47.    compile 'com.github.pagehelper:pagehelper-spring-boot-starter:1.2.10'

  48. }

这里同时也将SpringBoot升到了2.0,具体的新功能研究后会总结一下的

pagehelper这个插件估计和Spring1.5.x的版本有兼容性问题

上面的配置都是我测试好的,直接替换然后重新刷新Gradle

上篇的自动生成的mapper.xml文件中无查询全部的方法,这里补上一下

  1.    <select id="selectAreaAll" resultMap="BaseResultMap">

  2.        select

  3.        <include refid="Base_Column_List" />

  4.        from area

  5.    </select>


然后在dao借口插入方法接口 AreaMapper.java

  1. package com.example.dao;

  2. import com.example.entity.Area;

  3. import java.util.List;

  4. public interface AreaMapper {

  5.    int deleteByPrimaryKey(Integer id);

  6.    int insert(Area record);

  7.    int insertSelective(Area record);

  8.    Area selectByPrimaryKey(Integer id);

  9.    int updateByPrimaryKeySelective(Area record);

  10.    int updateByPrimaryKey(Area record);

  11.    /**

  12.     * 查询全部

  13.     * @return

  14.     */

  15.    List<Area> selectAreaAll();

  16. }

AreaService.java

  1. package com.example.service;

  2. import com.example.entity.Area;

  3. import java.util.List;

  4. /**

  5. * 这里给dao层的代码拷贝过来先使用

  6. * created by cfa  2018-11-08 下午 9:56

  7. **/

  8. public interface AreaService {

  9.    int deleteByPrimaryKey(Integer id);

  10.    int insert(Area record);

  11.    int insertSelective(Area record);

  12.    Area selectByPrimaryKey(Integer id);

  13.    int updateByPrimaryKeySelective(Area record);

  14.    int updateByPrimaryKey(Area record);

  15.    List<Area> selectAreaAll(Integer pageNum,Integer pageSize);

  16. }

上述接口的实现类加上 AreaServiceImpl.java

  1.    /**

  2.     *  分页核心代码

  3.     * @param pageNum

  4.     * @param pageSize

  5.     * @return

  6.     */

  7.    @Override

  8.    public List<Area> selectAreaAll(Integer pageNum,Integer pageSize) {

  9.        //这个要在你的查询之前加哦

  10.        PageHelper.startPage(pageNum,pageSize);

  11.        //这里直接查询全部就行了,分页插件会替你做分页,也无需担心性能问题,会自动补上limit的

  12.        List<Area> areaList=areaMapper.selectAreaAll();

  13.        return areaList;

  14.    }

控制层调用 AreaController.java

  1. package com.example.controller;

  2. import com.example.entity.Area;

  3. import com.example.service.AreaService;

  4. import org.springframework.beans.factory.annotation.Autowired;

  5. import org.springframework.web.bind.annotation.RequestMapping;

  6. import org.springframework.web.bind.annotation.RequestParam;

  7. import org.springframework.web.bind.annotation.RestController;

  8. import java.util.List;

  9. @RestController

  10. @RequestMapping("area")

  11. public class AreaController {

  12.    private final AreaService areaService;

  13.    @Autowired

  14.    public AreaController(AreaService areaService) {

  15.        this.areaService = areaService;

  16.    }

  17.    /**

  18.     * 这里的@RequestParam(name = "pagesize",required = false,defaultValue = "10")

  19.     * -name 为传输时为接受key为pagesize的参数

  20.     * -required 为是否为必须传输的参数

  21.     * -default 就是如果没有接收到值 就给予默认值

  22.     * @param pageNum

  23.     * @param pageSize

  24.     * @return

  25.     */

  26.    @RequestMapping("query")

  27.    public List<Area> areaList(@RequestParam(name = "pagenum",required = false,defaultValue = "1") Integer pageNum,

  28.                               @RequestParam(name = "pagesize",required = false,defaultValue = "10") Integer pageSize){

  29.        return areaService.selectAreaAll(pageNum,pageSize);

  30.    }

  31. }

然后在IDEA中启动DemoApplication启动类

用postman进行测试

postman下载地址:

https://www.cnblogs.com/wangfeng520/p/5892125.html


postman是一款可以用测试你接口的软件,推荐花个半个小时来熟悉下


到这里已经可以了

如果你的有问题,在我github有代码,或者百度下错误,因为每个人电脑的java版本不同,环境不同

3.API接口返回统一化

现在的很多项目都是前后端分离的项目,所以后台人员返回的参数参差不齐,每次对接都需要去交流一下,造成开发效率很低。

例如,一个操作更新成功,后台甲可能就返回给前台一个1,而乙返回一个Map格式,假如批量更新呢,返回的有时候不止是1了,所以接口返回统一化很重要。

萌新:那小哥,我又不是负责人,怎么统一呢
小哥:最少你自己用了之后返回的API的格式是固定的,前台很好拿数据
萌新:好的,好的开发规范,人人有责
小哥:和你说下阿里Java开发规范文档可以看下。


文档地址:https://files.cnblogs.com/files/han-1034683568/%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4Java%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C%E7%BB%88%E6%9E%81%E7%89%88v1.3.0.pdf
萌新:收到!

PageResultBean.java

  1. package com.example.beans;

  2. import com.github.pagehelper.PageInfo;

  3. import lombok.Getter;

  4. import java.io.Serializable;

  5. /*

  6. * description : 分页API统一返回的bean

  7. * @return

  8. * @time 2018-10-15 下午 9:29 根据晓风轻的ResultBean修改来的

  9. **/

  10. @Getter

  11. public class PageResultBean<T> extends ResultBean<T> implements Serializable {

  12.    // 总记录数

  13.    private long totalRecord;

  14.    //总页数

  15.    private int pageCount;

  16.    //当前页码

  17.    private int pageNo;

  18.    //当前页的记录数量

  19.    private int pageSize;

  20.    public PageResultBean(PageInfo<T> pageInfo) {

  21.        super.setData((T) pageInfo.getList());

  22.        this.setPageNo(pageInfo.getPageNum())

  23.                .setPageSize(pageInfo.getPageSize())

  24.                .setPageCount(pageInfo.getPages())

  25.                .setTotalRecord(pageInfo.getTotal());

  26.    }

  27.    public PageResultBean setTotalRecord(long totalRecord) {

  28.        this.totalRecord = totalRecord;

  29.        return this;

  30.    }

  31.    public PageResultBean setPageCount(int pageCount) {

  32.        this.pageCount = pageCount;

  33.        return this;

  34.    }

  35.    public PageResultBean setPageNo(int pageNo) {

  36.        this.pageNo = pageNo;

  37.        return this;

  38.    }

  39.    public PageResultBean setPageSize(int pageSize) {

  40.        this.pageSize = pageSize;

  41.        return this;

  42.    }

  43.    @Override

  44.    public String toString() {

  45.        return "PageResultBean{" +

  46.                "totalRecord=" + totalRecord +

  47.                ", pageCount=" + pageCount +

  48.                ", pageNo=" + pageNo +

  49.                ", pageSize=" + pageSize +

  50.                '}';

  51.    }

  52.    @Override

  53.    public PageResultBean setMsg(String msg) {

  54.        super.setMsg(msg);

  55.        return this;

  56.    }

  57.    @Override

  58.    public PageResultBean setCode(int code) {

  59.        super.setCode(code);

  60.        return this;

  61.    }

  62.    @Override

  63.    public PageResultBean setData(T data) {

  64.        super.setData(data);

  65.        return this;

  66.    }

  67. }

附上晓风轻所著的ResultBean(略有修改) ResultBean.java

  1. package com.example.beans;

  2. import lombok.Data;

  3. import lombok.NoArgsConstructor;

  4. import java.io.Serializable;

  5. @Data

  6. @NoArgsConstructor

  7. public class ResultBean<T> implements Serializable {

  8.    private static final long serialVersionUID = 1L;

  9.    public static final int NO_LOGIN = -1;

  10.    public static final int SUCCESS = 1;

  11.    public static final int FAIL = 0;

  12.    public static final int NO_PERMISSION = 2;

  13.    public static final int USERNAME_EXIST = -909;

  14.    private String msg = "success";

  15.    public static final String TOURIST = "游客";

  16.    private int code = SUCCESS;

  17.    private T data;

  18.    public ResultBean(T data) {

  19.        super();

  20.        this.data = data;

  21.    }

  22.    public ResultBean(Throwable e) {

  23.        super();

  24.        this.msg = e.toString();

  25.        this.code = FAIL;

  26.    }

  27.    public ResultBean setMsg(String msg) {

  28.        this.msg = msg;

  29.        return this;

  30.    }

  31.    public ResultBean setCode(int code) {

  32.        this.code = code;

  33.        return this;

  34.    }

  35.    public ResultBean setData(T data) {

  36.        this.data = data;

  37.        return this;

  38.    }

  39. }

上述两个Bean,基本所有的接口返回都可以使用,接口返回的统一化,也使得控制层的代码更加简洁

核心:接口返回bean的统一使AOP可以很好的管理,写好切入点,对于后续需要做的日志管理,以及方法运行时间,和全局异常处理,不能再好了

下面看下刚刚的控制层所修改后的效果

  1.    @GetMapping("query")

  2.    public PageResultBean<List<Area>> areaList(@RequestParam(name = "pagenum",required = false,defaultValue = "1") Integer pageNum,

  3.                                   @RequestParam(name = "pagesize",required = false,defaultValue = "10") Integer pageSize){

  4.        return new PageResultBean<List<Area>>(new PageInfo(areaService.selectAreaAll(pageNum,pageSize)));

  5.    }

还可以优化的就是两个参数的接受,以及后续可能会有的参数查询,可以使用PageResultBean和需要查询参数的实体类接收


下面启动DemoApplication

访问:http://localhost:8080/area/query?pagenum=1&pagesize=10


返回的JSON数据,包括了总页数,总条数,当前页数,每页条数等,表数据在data里,非常的实用

下面是data里的表数据

这里的显示JSON插件为:

https://chrome.google.com/webstore/detail/json-viewer/gbmdgpbipfallnflgajpaliibnhdgobh

谷歌浏览器里的,推荐使用。

代码的github地址:

https://github.com/cuifuan/springboot-demo


点击图片加入Spring交流群

↓↓↓

看完本文有收获?请转发分享给更多人

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存