【加精】Spring全家桶系列–SpringBoot渐入佳境

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 【加精】Spring全家桶系列–SpringBoot渐入佳境

//本文作者:cuifuan

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

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

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

小哥:那不是可以自动生成吗?

萌新:虽然可以自动生成,但是如果我要修改某个变量的数据类型,我岂不是还要去修改get/set方法?

小哥:哈哈,那我今天给你说一个插件,lombok可以解决你的问题

1.Lombok插件

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

1.1 代码演示

12345678910111213141516171819202122232425262728293031323334353637383940414243
package com.example.entity; public class Area {    private Integer id;     private Integer postalcode;     private String address;     private Integer type;     public Integer getId() {        return id;    }     public void setId(Integer id) {        this.id = id;    }     public Integer getPostalcode() {        return postalcode;    }     public void setPostalcode(Integer postalcode) {        this.postalcode = postalcode;    }     public String getAddress() {        return address;    }     public void setAddress(String address) {        this.address = address == null ? null : address.trim();    }     public Integer getType() {        return type;    }     public void setType(Integer type) {        this.type = type;    }}

package com.example.entity;

public class Area {
private Integer id;


private Integer postalcode;

private String address;

private Integer type;

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public Integer getPostalcode() {
    return postalcode;
}

public void setPostalcode(Integer postalcode) {
    this.postalcode = postalcode;
}

public String getAddress() {
    return address;
}

public void setAddress(String address) {
    this.address = address == null ? null : address.trim();
}

public Integer getType() {
    return type;
}

public void setType(Integer type) {
    this.type = type;
}

}

使用了Lombok之后

123456789101112131415
package com.example.entity; import lombok.Data; @Datapublic class Area {    private Integer id;     private Integer postalcode;     private String address;     private Integer type; }

package com.example.entity;

import lombok.Data;

@Data
public class Area {
private Integer id;


private Integer postalcode;

private String address;

private Integer type;

}

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

1.2 安装Lombok

在Intellij IDEA中安装lombok插件

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

安装完重启IDEA

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

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

123
//让gradle具有内置的compileOnly范围,可用于告诉gradle仅在编译期间添加lombok compileOnly 'org.projectlombok:lombok:1.18.4'

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

compileOnly ‘org.projectlombok:lombok:1.18.4’

刷新Gradle之后就可以了

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

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

1234567891011121314151617181920
package com.example.demo; import com.example.entity.Area;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class)@SpringBootTestpublic class DemoApplicationTests {     @Test    public void contextLoads() {        Area area=new Area();        //这里可以有get方法证明就ok 可以使用了        area.getType();    } }

package com.example.demo;

import com.example.entity.Area;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {


@Test
public void contextLoads() {
    Area area=new Area();
    //这里可以有get方法证明就ok 可以使用了
    area.getType();
}

}

2.PageHelper分页插件

萌新:小哥,我很苦恼分页这个功能怎么办?

小哥:那不是可以写好一个逻辑直接复制吗?

萌新:那也需要很多行代码,导致了需要在mapper以及业务层做很多无用功

小哥:哈哈,那我来告诉你一款分页插件,解决你的困扰

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

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
/** buildscript中的声明是gradle脚本自身需要使用的资源。 *  可以声明的资源包括依赖项、第三方插件、maven仓库地址等 */buildscript {    ext {        springBootVersion = '2.0.1.RELEASE'        mysqlVersion = '5.1.39'    }    repositories {        //使用国内源下载依赖        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }    }    dependencies {        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")    }}// 应用Java插件apply plugin: 'java'//让工程支持IDEA的导入apply plugin: 'idea'apply plugin: 'org.springframework.boot' group = 'com.example'version = '0.0.1-SNAPSHOT'sourceCompatibility = 1.8//build.gradle文件中直接声明的依赖项、仓库地址等信息是项目自身需要的资源。repositories {    maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }    mavenCentral()} /** * 在gradle里,对依赖的定义有6种 * compile, runtime, testCompile, testRuntime, providedCompile,providedRuntime * compile:需要引用这个库才能进行编译工作 * testRuntime : 测试依赖范围 * 其他的了解:http://shmilyaw-hotmail-com.iteye.com/blog/2345439 */dependencies {    compile('org.springframework.boot:spring-boot-starter-web:2.0.1.RELEASE')    compile('com.alibaba:druid:1.0.29')    testCompile('org.springframework.boot:spring-boot-starter-test:2.0.1.RELEASE')    //这里的版本可以在上述定义    compile 'mysql:mysql-connector-java:5.1.39'    compile 'org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2'    //让gradle具有内置的compileOnly范围,可用于告诉gradle仅在编译期间添加lombok    compileOnly 'org.projectlombok:lombok:1.18.4'    //分页插件    compile 'com.github.pagehelper:pagehelper-spring-boot-starter:1.2.10'}

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

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

*/
buildscript {
ext {
springBootVersion = ‘2.0.1.RELEASE’
mysqlVersion = ‘5.1.39’
}
repositories {
//使用国内源下载依赖
maven { url ‘http://maven.aliyun.com/nexus/content/groups/public/' }
}
dependencies {
classpath(“org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}”)
}
}
// 应用Java插件
apply plugin: ‘java’
//让工程支持IDEA的导入
apply plugin: ‘idea’
apply plugin: ‘org.springframework.boot’

group = ‘com.example’
version = ‘0.0.1-SNAPSHOT’
sourceCompatibility = 1.8
//build.gradle文件中直接声明的依赖项、仓库地址等信息是项目自身需要的资源。
repositories {
maven { url ‘http://maven.aliyun.com/nexus/content/groups/public/' }
mavenCentral()
}

/**

  • 在gradle里,对依赖的定义有6种
  • compile, runtime, testCompile, testRuntime, providedCompile,providedRuntime
  • compile:需要引用这个库才能进行编译工作
  • testRuntime : 测试依赖范围
  • 其他的了解:http://shmilyaw-hotmail-com.iteye.com/blog/2345439

*/
dependencies {
compile(‘org.springframework.boot:spring-boot-starter-web:2.0.1.RELEASE’)
compile(‘com.alibaba:druid:1.0.29’)
testCompile(‘org.springframework.boot:spring-boot-starter-test:2.0.1.RELEASE’)
//这里的版本可以在上述定义
compile ‘mysql:mysql-connector-java:5.1.39’
compile ‘org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2’
//让gradle具有内置的compileOnly范围,可用于告诉gradle仅在编译期间添加lombok
compileOnly ‘org.projectlombok:lombok:1.18.4’
//分页插件
compile ‘com.github.pagehelper:pagehelper-spring-boot-starter:1.2.10’
}

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

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

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

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

12345
select id="selectAreaAll" resultMap="BaseResultMap"        select        include refid="Base_Column_List" /        from area    /select

select id=”selectAreaAll” resultMap=”BaseResultMap”
select
include refid=”Base_Column_List” /
from area
/select

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

12345678910111213141516171819202122232425
package com.example.dao; import com.example.entity.Area; import java.util.List; public interface AreaMapper {    int deleteByPrimaryKey(Integer id);     int insert(Area record);     int insertSelective(Area record);     Area selectByPrimaryKey(Integer id);     int updateByPrimaryKeySelective(Area record);     int updateByPrimaryKey(Area record);     /**     * 查询全部     * @return     */    ListArea selectAreaAll();}

package com.example.dao;

import com.example.entity.Area;

import java.util.List;

public interface AreaMapper {
int deleteByPrimaryKey(Integer id);


int insert(Area record);

int insertSelective(Area record);

Area selectByPrimaryKey(Integer id);

int updateByPrimaryKeySelective(Area record);

int updateByPrimaryKey(Area record);

/**
 * 查询全部
 * @return
 */
ListArea selectAreaAll();

}

AreaService.java

12345678910111213141516171819202122232425262728
package com.example.service; import com.example.entity.Area; import java.util.List; /** * 这里给dao层的代码拷贝过来先使用 * created by cfa  2018-11-08 下午 9:56 **/public interface AreaService {      int deleteByPrimaryKey(Integer id);     int insert(Area record);     int insertSelective(Area record);     Area selectByPrimaryKey(Integer id);     int updateByPrimaryKeySelective(Area record);     int updateByPrimaryKey(Area record);     ListArea selectAreaAll(Integer pageNum,Integer pageSize); }

package com.example.service;

import com.example.entity.Area;

import java.util.List;

/**

  • 这里给dao层的代码拷贝过来先使用
  • created by cfa 2018-11-08 下午 9:56

**/
public interface AreaService {


int deleteByPrimaryKey(Integer id);

int insert(Area record);

int insertSelective(Area record);

Area selectByPrimaryKey(Integer id);

int updateByPrimaryKeySelective(Area record);

int updateByPrimaryKey(Area record);

ListArea selectAreaAll(Integer pageNum,Integer pageSize);

}

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

1234567891011121314
/**     *  分页核心代码     * @param pageNum     * @param pageSize     * @return     */    @Override    public ListArea selectAreaAll(Integer pageNum,Integer pageSize) {        //这个要在你的查询之前加哦        PageHelper.startPage(pageNum,pageSize);        //这里直接查询全部就行了,分页插件会替你做分页,也无需担心性能问题,会自动补上limit的        ListArea areaList=areaMapper.selectAreaAll();        return areaList;    }

/**
* 分页核心代码
* @param pageNum
* @param pageSize
* @return
*/
@Override
public ListArea selectAreaAll(Integer pageNum,Integer pageSize) {
//这个要在你的查询之前加哦
PageHelper.startPage(pageNum,pageSize);
//这里直接查询全部就行了,分页插件会替你做分页,也无需担心性能问题,会自动补上limit的
ListArea areaList=areaMapper.selectAreaAll();
return areaList;
}

控制层调用 AreaController.java

1234567891011121314151617181920212223242526272829303132333435363738
package com.example.controller;  import com.example.entity.Area;import com.example.service.AreaService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController@RequestMapping("area")public class AreaController {     private final AreaService areaService;     @Autowired    public AreaController(AreaService areaService) {        this.areaService = areaService;    }     /**     * 这里的@RequestParam(name = "pagesize",required = false,defaultValue = "10")     * -name 为传输时为接受key为pagesize的参数     * -required 为是否为必须传输的参数     * -default 就是如果没有接收到值 就给予默认值     * @param pageNum     * @param pageSize     * @return     */    @RequestMapping("query")    public ListArea areaList(@RequestParam(name = "pagenum",required = false,defaultValue = "1") Integer pageNum,                               @RequestParam(name = "pagesize",required = false,defaultValue = "10") Integer pageSize){        return areaService.selectAreaAll(pageNum,pageSize);    }}

package com.example.controller;

import com.example.entity.Area;
import com.example.service.AreaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping(“area”)
public class AreaController {


private final AreaService areaService;

@Autowired
public AreaController(AreaService areaService) {
    this.areaService = areaService;
}

/**
 * 这里的@RequestParam(name = "pagesize",required = false,defaultValue = "10")
 * -name 为传输时为接受key为pagesize的参数
 * -required 为是否为必须传输的参数
 * -default 就是如果没有接收到值 就给予默认值
 * @param pageNum
 * @param pageSize
 * @return
 */
@RequestMapping("query")
public ListArea areaList(@RequestParam(name = "pagenum",required = false,defaultValue = "1") Integer pageNum,
                           @RequestParam(name = "pagesize",required = false,defaultValue = "10") Integer pageSize){
    return areaService.selectAreaAll(pageNum,pageSize);
}

}

然后在IDEA中启动DemoApplication启动类

用postman进行测试

postman下载地址:
https://www.cnblogs.com/wangfeng520/p/5892125.html
postman是一款可以用测试你接口的软件,推荐花个半个小时来熟悉下

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

到这里已经可以了

如果你的有问题,在我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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
package com.example.beans; import com.github.pagehelper.PageInfo;import lombok.Getter; import java.io.Serializable; /* * description : 分页API统一返回的bean * @return * @time 2018-10-15 下午 9:29 根据晓风轻的ResultBean修改来的 **/@Getterpublic class PageResultBeanT extends ResultBeanT implements Serializable {     // 总记录数    private long totalRecord;     //总页数    private int pageCount;     //当前页码    private int pageNo;     //当前页的记录数量    private int pageSize;     public PageResultBean(PageInfoT pageInfo) {        super.setData((T) pageInfo.getList());        this.setPageNo(pageInfo.getPageNum())                .setPageSize(pageInfo.getPageSize())                .setPageCount(pageInfo.getPages())                .setTotalRecord(pageInfo.getTotal());    }     public PageResultBean setTotalRecord(long totalRecord) {        this.totalRecord = totalRecord;        return this;    }     public PageResultBean setPageCount(int pageCount) {        this.pageCount = pageCount;        return this;    }     public PageResultBean setPageNo(int pageNo) {        this.pageNo = pageNo;        return this;    }     public PageResultBean setPageSize(int pageSize) {        this.pageSize = pageSize;        return this;    }     @Override    public String toString() {        return "PageResultBean{" +                "totalRecord=" + totalRecord +                ", pageCount=" + pageCount +                ", pageNo=" + pageNo +                ", pageSize=" + pageSize +                '}';    }     @Override    public PageResultBean setMsg(String msg) {        super.setMsg(msg);        return this;    }     @Override    public PageResultBean setCode(int code) {        super.setCode(code);        return this;    }     @Override    public PageResultBean setData(T data) {        super.setData(data);        return this;    } }

package com.example.beans;

import com.github.pagehelper.PageInfo;
import lombok.Getter;

import java.io.Serializable;

/*

  • description : 分页API统一返回的bean
  • @return
  • @time 2018-10-15 下午 9:29 根据晓风轻的ResultBean修改来的

**/
@Getter
public class PageResultBean extends ResultBean implements Serializable {


// 总记录数
private long totalRecord;

//总页数
private int pageCount;

//当前页码
private int pageNo;

//当前页的记录数量
private int pageSize;

public PageResultBean(PageInfo pageInfo) {
    super.setData((T) pageInfo.getList());
    this.setPageNo(pageInfo.getPageNum())
            .setPageSize(pageInfo.getPageSize())
            .setPageCount(pageInfo.getPages())
            .setTotalRecord(pageInfo.getTotal());
}

public PageResultBean setTotalRecord(long totalRecord) {
    this.totalRecord = totalRecord;
    return this;
}

public PageResultBean setPageCount(int pageCount) {
    this.pageCount = pageCount;
    return this;
}

public PageResultBean setPageNo(int pageNo) {
    this.pageNo = pageNo;
    return this;
}

public PageResultBean setPageSize(int pageSize) {
    this.pageSize = pageSize;
    return this;
}

@Override
public String toString() {
    return "PageResultBean{" +
            "totalRecord=" + totalRecord +
            ", pageCount=" + pageCount +
            ", pageNo=" + pageNo +
            ", pageSize=" + pageSize +
            '}';
}

@Override
public PageResultBean setMsg(String msg) {
    super.setMsg(msg);
    return this;
}

@Override
public PageResultBean setCode(int code) {
    super.setCode(code);
    return this;
}

@Override
public PageResultBean setData(T data) {
    super.setData(data);
    return this;
}

}

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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
package com.example.beans; import lombok.Data;import lombok.NoArgsConstructor; import java.io.Serializable; @Data@NoArgsConstructorpublic class ResultBeanT implements Serializable {     private static final long serialVersionUID = 1L;     public static final int NO_LOGIN = -1;     public static final int SUCCESS = 1;     public static final int FAIL = 0;     public static final int NO_PERMISSION = 2;     public static final int USERNAME_EXIST = -909;     private String msg = "success";     public static final String TOURIST = "游客";     private int code = SUCCESS;     private T data;     public ResultBean(T data) {        super();        this.data = data;    }     public ResultBean(Throwable e) {        super();        this.msg = e.toString();        this.code = FAIL;    }     public ResultBean setMsg(String msg) {        this.msg = msg;        return this;    }     public ResultBean setCode(int code) {        this.code = code;        return this;    }     public ResultBean setData(T data) {        this.data = data;        return this;    }}

package com.example.beans;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@NoArgsConstructor
public class ResultBean implements Serializable {


private static final long serialVersionUID = 1L;

public static final int NO_LOGIN = -1;

public static final int SUCCESS = 1;

public static final int FAIL = 0;

public static final int NO_PERMISSION = 2;

public static final int USERNAME_EXIST = -909;

private String msg = "success";

public static final String TOURIST = "游客";

private int code = SUCCESS;

private T data;

public ResultBean(T data) {
    super();
    this.data = data;
}

public ResultBean(Throwable e) {
    super();
    this.msg = e.toString();
    this.code = FAIL;
}

public ResultBean setMsg(String msg) {
    this.msg = msg;
    return this;
}

public ResultBean setCode(int code) {
    this.code = code;
    return this;
}

public ResultBean setData(T data) {
    this.data = data;
    return this;
}

}

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

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

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

12345
@GetMapping("query")    public PageResultBeanListArea areaList(@RequestParam(name = "pagenum",required = false,defaultValue = "1") Integer pageNum,                                   @RequestParam(name = "pagesize",required = false,defaultValue = "10") Integer pageSize){        return new PageResultBeanListArea(new PageInfo(areaService.selectAreaAll(pageNum,pageSize)));    }

@GetMapping(“query”)
public PageResultBeanListArea areaList(@RequestParam(name = “pagenum”,required = false,defaultValue = “1”) Integer pageNum,
@RequestParam(name = “pagesize”,required = false,defaultValue = “10”) Integer pageSize){
return new PageResultBeanListArea(new PageInfo(areaService.selectAreaAll(pageNum,pageSize)));
}

还可以优化的就是两个参数的接受,以及后续可能会有的参数查询,可以使用PageResultBean和需要查询参数的实体类接收
下面启动DemoApplication
访问:http://localhost:8080/area/query?pagenum=1&pagesize=10
返回的JSON数据,包括了总页数,总条数,当前页数,每页条数等,表数据在data里,非常的实用

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

下面是data里的表数据

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

这里的显示JSON插件为:
https://chrome.google.com/webstore/detail/json-viewer/gbmdgpbipfallnflgajpaliibnhdgobh
谷歌浏览器里的,推荐使用。
代码的github地址:
https://github.com/cuifuan/springboot-demo

** **

点击图片加入Spring交流群

↓↓↓

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

Spring全家桶系列--SpringBoot渐入佳境
本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 【加精】Spring全家桶系列–SpringBoot渐入佳境


 上一篇
SpringBoot配置原理快速入门 SpringBoot配置原理快速入门
Author:Alan 公众号:阿风的JAVA 本篇文章需要对spirng有所了解 对于Spring Boot其并不是一个框架。其整合原理是Sping对技术的整合。不过与传统xml不同的是它推荐使用的 java配置文件的整合形式。那么
下一篇 
Springboot webSocket(二) Springboot webSocket(二)
本文将通过搭建一个一对一聊天服务器,深入学习更多的socket知识。 1、发送消息在前面我们写了一个自动回复的小例子,用到了 @MessageMapping("/hello")和 @SendTo("/top