Java后端爱上SpringBoot 第一节:一个简单的增删改查


PS:贫道是后端开发工程师,本片博客是后端做的符合restful api的增删改查接口

SpringBoot的魅力

SpringBoot大大的 简化了后端开发,用过SpringMVC的朋友都知道,大量的Spring配置文件烦的一笔,本文讲述了Spring Boot的应用和一些后端开发的东西。说实话,这样的简单开发过程会慢慢的被代码生成工具和AI写代码所替代,大量的程序员将要失业啦!

一些链接

本人用的SpringBoot 2.1.1版本,官网文档先贴上:
链接: Spring Boot 2.1.1 官网文档.

本文标签

  • SpringBoot
  • Spring-Data-Jpa
  • Swagger
  • MySql

开发工具

有的人喜欢用IDEA有些人喜欢用Eclipse,关于工具的选择和自身环境有关,比如:公司的人都在用Eclipse,你用IDEA,别人的项目拿过来会有坑,你的项目拿过去别人不能用。贫道使用的是Eclipse+SpringBoot插件。
插件链接奉上: Spring Boot Eclipse插件(Spring Tool Suite).

Begin Hello World

废话不说,装好JDK,Eclipse,Spring插件以后,配置Eclipse的JDK,配置maven 3.5.4,开始我们的SpringBoot HelloWorld
在这里插入图片描述
把这些东西都加上,后面会用到:
在这里插入图片描述

maven现在开始导入Spring Boot,贫道使用的是阿里源
在这里插入图片描述

在maven配置里面把maven默认的源改为如下:
E:\apache-maven-3.5.4\conf\settings.xml

<mirror>  
    <id>nexus-aliyun</id>  
    <mirrorOf>central</mirrorOf>    
    <name>Nexus aliyun</name>  
    <url>http://maven.aliyun.com/nexus/content/groups/public</url>  
</mirror>

OK,下载完之后,启动工程以前,有几个坑要说一下:

  1. 将application.properties转换成application.yml,因为application.properties的默认编码为ISO-8859-1,之后有中文的时候,用@Value注释的中文一直是乱码,只有改成yml文件才会显示中文,至于其他解决application.properties乱码的方法,贫道试了好几种,都不管用,所以改成了application.yml文件。
  2. 连接Mysql的驱动改为8.0版本,因为贫道的机器上装的是MySql8.0,用之前老的驱动不能连接。为什么用8.0的Mysql,因为Mysql官网发布,8.0的Mysql的性能比5.7的Mysql高了两倍,还有其他好东西,有兴趣的道友可自行查找Mysql相关资料。
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.11</version><!--$NO-MVN-MAN-VER$ -->
		</dependency>
  1. 配置连接Mysql连接
spring:
 datasource:
   driver-class-name: com.mysql.cj.jdbc.Driver
   url: jdbc:mysql://127.0.0.1:3306/spring?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&allowPublicKeyRetrieval=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
   username: hyn
   password: hyn1234

url驱动说明:characterEncoding=UTF-8 指定字符集。
useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai 指定时区,不然插入数据库时间和当前时间差8个小时。
还要更改Mysql8.0密码验证方式,这个大家在网上一搜就有,这里就不说了。

com.mysql.cj.jdbc.Driver 这个东西是Mysql8.0的新驱动

好了,坑填完了,启动一下:

项目目录结构

在这里插入图片描述
用了3秒启动起来了。这比SpringMvc启动快了很多,这还是SpringBoot没有优化启动的结果。

写一个用户的增删改查

第一个Controller,基本每个系统都有用户,那贫道就先写一个用户增删改查
包的目录接口献上:
工程目录结构
解释一哈:

//系统配置包
com.hyn.spring.config
//前端控制器
com.hyn.spring.controller
//实体
com.hyn.spring.domain
//数据访问层
com.hyn.spring.repository
//业务接口
com.hyn.spring.service
//业务实现
com.hyn.spring.service.impl
//视图包
com..hyn.spring.vo

实体

不说了贴代码,省略get set:

package com.hyn.spring.domain;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.UpdateTimestamp;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

/**
 * 
* @Title: SysUser.java
* @Package com.hyn.spring.domain
* @Description: TODO
* @author hyn  
* @date 2018年12月9日 下午1:38:53
* @version V1.0  
 */
@Entity
@Table(name = "sys_user")
@EntityListeners(AuditingEntityListener.class)
public class SysUser implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Id
	@GenericGenerator(name = "idGenerator", strategy = "uuid") // 这个是hibernate的注解/生成32位UUID
	@GeneratedValue(generator = "idGenerator")
	/**
	 *  用户ID
	 */
	@Column(columnDefinition="varchar(36)  not null  comment '用户ID'  ")
	String id;

	/**
	 * 
	 * 用户状态
	 */
	@Column(columnDefinition = "enum('true','false') default  'true' not null comment '用户状态' ")
	String status;

	/**
	 *  邮箱
	 */
	@Column(columnDefinition = "varchar(20)  not null  default '' comment '用户邮箱'" )
	private String email;

	/**
	 *  登录用户名
	 */
	@Column(columnDefinition = "varchar(20)  not null unique default '' comment '登录用户名'" )
	private String loginName;

	/**
	 *  用户名
	 */
	@Column(columnDefinition = "varchar(10)  not null  default '' comment '用户名称'" )
	private String userName;

	/**
	 *  密码
	 */
	@Column(columnDefinition = "varchar(100)  not null  default '888888' comment '登录密码'" )
	private String password;

	/**
	 *  电话
	 */
	@Column(columnDefinition = "varchar(11)  not null unique default '' comment '手机号码'" )
	private String phone;

	/**
	 *  更新时间
	 */
	@Temporal(TemporalType.TIMESTAMP)    
	@Column(columnDefinition = "timestamp  default current_timestamp on update current_timestamp comment '更新时间'")
	@UpdateTimestamp
	private Date moditime;
	//省略 get set
}

在application.yml文件中加入Spring-data-jpa配置:

spring:
###JPA配置
  jpa:
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        dialect: org.hibernate.dialect.MySQL5InnoDBDialect
    show-sql: true
    generate-ddl: true
    database: mysql 

这里再启动一下工程,使用spring-data-jpa自动生成表的功能,至于spring-data-jpa到底是什么,干啥的,怎么用,有兴趣的道友可以提前看下,以后贫道的博客会有介绍。
控制台会打印出建表语句,:

建表语句
不放心的话去数据库看看:
在这里插入图片描述
表结构如下:
表结构
表建好了,接下来做一下数据访问层。

数据访问层

package com.hyn.spring.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

import com.hyn.spring.domain.SysUser;

public interface ISysUserRepository extends JpaRepository<SysUser, String>,JpaSpecificationExecutor<SysUser>{

}

你没有看错,就这个,数据访问层就完了,完全可以实现增删改查。

视图层

接下来定义和前端交互的数据格式,新建一个SysUserVO类,但是作为一个合格的后端开发者,贫道定义的数据格式还要每个都和前端的道友说一遍吗?NO,那怎么办?使用Swagger来书写贫道和前端道友交互的接口文档。
附上swagger使用的几篇文章:
Spring Boot中使用Swagger2构建强大的RESTful API文档
SpringBoot 使用Swagger2打造在线接口文档

maven引入swagge:

        <dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger2</artifactId>
			<version>2.8.0</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger-ui</artifactId>
			<version>2.8.0</version>
		</dependency>

Swagger配置:

package com.hyn.spring.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.google.common.base.Predicates;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * 
* @Title: SwaggerConfigurer.java
* @Package com.hyn.spring.config
* @Description: TODO
* @author hyn  
* @date 2018年12月9日 下午3:00:05
* @version V1.0  
 */
@Configuration
@EnableSwagger2
public class SwaggerConfigurer {
	@Bean
	public Docket createRestApi() {
		//错误路径不监控
		return new Docket(DocumentationType.SWAGGER_2).select()
				.apis(RequestHandlerSelectors.any())
                .paths(Predicates.not(PathSelectors.regex("/error.*")))
				.build()
				.apiInfo(buildApiInf());
	}


	private ApiInfo buildApiInf() {
		return new ApiInfoBuilder().title("spring-first接口文档").description("api文档")
				.version("0.0.1").build();

	}
}

新建的SysUserVO如下:

package com.hyn.spring.vo;


import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value="用户")
public class SysUserVO {
	
	@ApiModelProperty(value = "id", name = "id")
	String id;

	/**
	 * 
	 * 用户状态
	 */
	@ApiModelProperty(value = "用户状态", name = "status")
	String status;

	/**
	 *  邮箱
	 */
	@ApiModelProperty(value = "邮箱", name = "email")
	private String email;

	/**
	 *  登录用户名
	 */
	@ApiModelProperty(value = "登录用户名", name = "loginName")
	private String loginName;

	/**
	 *  用户名
	 */
	@ApiModelProperty(value = "用户名", name = "userName")
	private String userName;


	/**
	 *  电话
	 */
	@ApiModelProperty(value = "电话", name = "phone")
	private String phone;
    //同样省略get set

业务层

首先是定义需要实现的接口,接下来是实现。

业务接口

package com.hyn.spring.service;

import org.springframework.data.domain.Page;

import com.hyn.spring.vo.SysUserVO;

public interface ISysUserService {
	
	/**
	 * 增加一个用户
	 * @return
	 */
	String save(SysUserVO sysUserVO);
	
	/**
	 * 删除一个用户
	 * @return
	 */
	String delete(String id);
	
	/**
	 * 更新一个用户
	 * @return
	 */
	String update(SysUserVO sysUserVO);
	
	/**
	 * 分页查询用户
	 * @param userName用户名
	 * @param pageable 分页查询条件
	 * @return
	 */
	Page<SysUserVO> getSysUser(String userName,Pageable pageable);
}

业务实现

package com.hyn.spring.service.impl;

import java.util.LinkedList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;

import com.hyn.spring.domain.SysUser;
import com.hyn.spring.repository.ISysUserRepository;
import com.hyn.spring.service.ISysUserService;
import com.hyn.spring.utils.IPageResponse;
import com.hyn.spring.vo.SysUserVO;

@Service
public class ISysUserServiceImpl implements ISysUserService {

	@Autowired
	ISysUserRepository iSysUserRepository;

	@Override
	public String save(SysUserVO sysUserVO) {

		SysUser sysUser = new SysUser();
		sysUser.setEmail(sysUserVO.getEmail());
		sysUser.setLoginName(sysUserVO.getLoginName());
		sysUser.setPassword(sysUserVO.getPassword());
		sysUser.setPhone(sysUserVO.getPhone());
		sysUser.setStatus(sysUserVO.getStatus());
		sysUser.setUserName(sysUserVO.getUserName());
		iSysUserRepository.save(sysUser);
		return "success";
	}

	@Override
	public String delete(String id) {
		iSysUserRepository.deleteById(id);
		return "success";
	}

	@Override
	public String update(SysUserVO sysUserVO) {
		SysUser sysUser = new SysUser();
		sysUser.setEmail(sysUserVO.getEmail());
		sysUser.setLoginName(sysUserVO.getLoginName());
		sysUser.setPassword(sysUserVO.getPassword());
		sysUser.setPhone(sysUserVO.getPhone());
		sysUser.setStatus(sysUserVO.getStatus());
		sysUser.setUserName(sysUserVO.getUserName());
		sysUser.setId(sysUserVO.getId());
		iSysUserRepository.saveAndFlush(sysUser);
		return "success";
	}

	@Override
	public Page<SysUserVO> getSysUser(String userName, Pageable pageable) {

		Page<SysUser> page = iSysUserRepository.findAll(this.getWhereClause(userName), pageable);

		List<SysUserVO> voList = new LinkedList<>();
		for (SysUser sysUser : page.getContent()) {
			SysUserVO sysUserVO = new SysUserVO();
			sysUserVO.setEmail(sysUser.getEmail());
			sysUserVO.setId(sysUser.getId());
			sysUserVO.setLoginName(sysUser.getLoginName());
			sysUserVO.setPassword(sysUser.getPassword());
			sysUserVO.setPhone(sysUser.getPhone());
			sysUserVO.setStatus(sysUser.getStatus());
			sysUserVO.setUserName(sysUser.getUserName());
			voList.add(sysUserVO);
		}
		Page<SysUserVO> voPage = new IPageResponse<>(voList, pageable, page.getTotalElements());
		return voPage;
	}

	/**
	 * 构造断言
	 * 
	 * @param userName
	 * @return
	 */
	private Specification<SysUser> getWhereClause(String userName) {
		return new Specification<SysUser>() {

			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<SysUser> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				Predicate predicate = criteriaBuilder.conjunction();

				if (StringUtils.isEmpty(userName)) {
					predicate.getExpressions()
							.add(criteriaBuilder.notLike(root.<String>get("userName"), "%" + userName + "%"));
				}
				return predicate;
			}
		};
	}
}

这里有个坑要注意:因为我们返回给前端的分页数据是从0开始的,但是前端需要是从1开始,所有我们要重写JPA的PageImpl,代码如下:

package com.hyn.spring.utils;

import java.util.List;

import org.springframework.data.domain.AbstractPageRequest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;

/**
 * 
* @Title: IPageResponse.java
* @Package com.hyn.spring.utils
* @Description: TODO
* @author hyn  
* @date 2018年12月9日 下午2:48:16
* @version V1.0  
 */
public class IPageResponse<T> extends PageImpl<T> implements Page<T> {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public IPageResponse(List<T> content, Pageable pageable, long total) {
		super(content, pageable, total);
	}

	/**
	* 重写当前页,将当前页加1返回前台,spring data jpa起始页0加1后返回前台
	* @return
	*/
	@Override
	public int getNumber() {
		return super.getNumber() + 1;
	}
	
	@Override
	public Pageable getPageable() {
		return null;
	}

	public static Page<?> getResponsePage(Page<?> page, AbstractPageRequest pageRequest) {
		if (page == null || page.getContent() ==null || page.getContent().size()==0) {
			return null;
		} else {
			return new IPageResponse<>(page.getContent(), pageRequest, page.getTotalElements());
		}
	}
}

控制层

给前端发布的restful api接口。

package com.hyn.spring.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.hyn.spring.service.ISysUserService;
import com.hyn.spring.utils.IPageRequest;
import com.hyn.spring.vo.SysUserVO;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@Api(value = "user", tags = "系统用户模块")
@Controller(value = "user")
@RequestMapping(value = "/user")
public class SysUserController {

	@Autowired
	ISysUserService iSysUserService;

	/**
	 * 
	 * @param sysUserVO
	 * @return
	 */
	@ApiOperation(value = "新增用户接口")
	@RequestMapping(value = "/", method = RequestMethod.POST)
	@ResponseBody
	public String saveUser(@ApiParam(value = "用戶信息", required = true) @RequestBody SysUserVO sysUserVO) {
		String resultCode = iSysUserService.save(sysUserVO);
		return resultCode;
	}

	/**
	 * 
	 * @param id
	 * @return
	 */
	@ApiOperation(value = "删除用户接口")
	@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
	@ResponseBody
	public String delete(@ApiParam(value = "用户ID", required = true) @PathVariable(name = "id") String id) {
		String resultCode = iSysUserService.delete(id);
		return resultCode;
	}

	/**
	 * 
	 * @param sessionSysUser
	 * @return IResult
	 */
	@ApiOperation(value = "更新用户信息")
	@RequestMapping(value = "/", method = RequestMethod.PUT)
	@ResponseBody
	public String update(@ApiParam(value = "用戶信息", required = true) @RequestBody SysUserVO sysUserVO) {
		String resultCode = iSysUserService.update(sysUserVO);
		return resultCode;
	}

	/**
	 * 
	 * 查询用户 分页查询
	 * 
	 */
	@ApiOperation(value = "查询用户信息")
	@RequestMapping(value = "/", method = RequestMethod.GET)
	@ResponseBody
	public Page<SysUserVO> getSysUser(
			@ApiParam(value = "用户名称", required = false) @RequestParam(name = "userName", required = false) String userName,
			@ApiParam(value = "排序方式", required = false) @RequestParam(name = "sort", required = false) String sort,
			@ApiParam(value = "排序字段", required = false) @RequestParam(name = "sidx", required = false) String sidx,
			@ApiParam(value = "页码", required = false) @RequestParam(name = "page", required = false) Integer page,
			@ApiParam(value = "页大小", required = false) @RequestParam(name = "size", required = false) Integer size) {
		IPageRequest iPageRequest = new IPageRequest(sort, sidx, page, size);
		Page<SysUserVO> sysUsers = iSysUserService.getSysUser(userName, iPageRequest.getRequestPage());
		return sysUsers;
	}
}

这里需要自定义一个请求封装类IPageRequest,用来接收前端的分页参数:

package com.hyn.spring.utils;

import org.springframework.data.domain.AbstractPageRequest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.util.StringUtils;

/**
 * 
* @Title: IPageRequest.java
* @Package com.hyn.spring.utils
* @Description: TODO
* @author hyn  
* @date 2018年12月9日 下午3:19:09
* @version V1.0  
 */
public class IPageRequest {

	/**
	 * 排序方式
	 */
	String sort;

	/**
	 * 排序字段
	 */
	String sidx;
	/**
	 * 当前頁面
	 */
	Integer page=0;
	/**
	 * 页大小
	 */
	Integer size=0;

	public String getSort() {
		return sort;
	}

	public void setSort(String sort) {
		this.sort = sort;
	}

	public String getSidx() {
		return sidx;
	}

	public void setSidx(String sidx) {
		this.sidx = sidx;
	}

	public Integer getPage() {
		return page;
	}

	public void setPage(Integer page) {
		this.page = page;
	}

	public Integer getSize() {
		return size;
	}

	public void setSize(Integer size) {
		this.size = size;
	}

	public IPageRequest(String sort, String sidx, Integer page, Integer size) {
		super();
		this.sort = sort;
		this.sidx = sidx;
		this.page = page;
		this.size = size;
	}

	public IPageRequest() {
		super();
	}

	@Override
	public String toString() {
		return "IPageRequest [sort=" + sort + ", sidx=" + sidx + ", page=" + page + ", size=" + size + "]";
	}

	public AbstractPageRequest getRequestPage() {

		Sort mysort = null;
		if (StringUtils.isEmpty(this.sidx)) {
			this.sidx="moditime";
		}
		if (StringUtils.isEmpty(this.sort)) {
			mysort = new Sort(Sort.Direction.DESC, this.sidx);
		} else {
			if (Sort.Direction.DESC.name().equals(this.sort.toUpperCase())) {
				mysort = new Sort(Sort.Direction.DESC, this.sidx);
			} else {
				mysort = new Sort(Sort.Direction.ASC, this.sidx);
			}
		}
		
		int pagTmp = 0;
		int sizeTmp = 0;
		if (this.page == null || this.page < 1) {
			pagTmp = 0;
		} else {
			pagTmp = this.page - 1;
		}

		if (this.size==null || this.size <= 0) {
			sizeTmp = 15;
		}else
		{
			sizeTmp = this.size;
		}
		AbstractPageRequest pageable =null;
		if(mysort!=null)
		{
			pageable=PageRequest.of(pagTmp, sizeTmp, mysort);
		}
		return pageable;
	}
}

测试

好了,所有的代码都贴完了,测一下:
给项目加个path,给application.yml添加:

server:
  servlet:
    context-path: /api/

启动项目,输入:http://127.0.0.1:8080/api/swagger-ui.html在这里插入图片描述

新增用户

在这里插入图片描述

查询用户

在这里插入图片描述
在这里插入图片描述

修改

在这里插入图片描述

删除

在这里插入图片描述

好了,有些累,有问题可留言!

猜你喜欢

转载自blog.csdn.net/baidu_37307156/article/details/84927710