一、项目搭建后端环境:
1.新建springboot工程:
2.2.1
1.最顶层的父工程yygh-parent的构建:
第一项:添加打包方式为pom
<packaging>pom</packaging>
第二项:properties标签定义我们此项目要使用的各种依赖的版本号
<!--properties属性:使用自定义标签统一声明版本号-->
<properties>
<java.version>1.8</java.version>
<cloud.version>Hoxton.RELEASE</cloud.version>
<alibaba.version>2.2.0.RELEASE</alibaba.version>
<mybatis-plus.version>3.4.2</mybatis-plus.version>
<mysql.version>8.0.22</mysql.version>
<swagger.version>2.7.0</swagger.version>
<jwt.version>0.7.0</jwt.version>
<fastjson.version>1.2.29</fastjson.version>
<httpclient.version>4.5.1</httpclient.version>
<easyexcel.version>2.2.0-beta2</easyexcel.version>
<aliyun.version>4.1.1</aliyun.version>
<oss.version>3.9.1</oss.version>
<jodatime.version>2.10.1</jodatime.version>
</properties>
第三项:依赖管理器声明依赖:
注意:配置dependencyManagement,依赖管理器只锁定各种依赖和版本,只是对版本进行管理,不会实际引入jar
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mybatis-plus 持久层-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
最顶层的父工程配置所需的:properties,dependencyManagement,build
pom爆红的话,先注释掉dependencyManagement,然后下载,下载好后加上dependencyManagement标签,刷新maven就好了。
yygh_parent的pom:
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modules>
<module>common</module>
<module>model</module>
<module>service</module>
</modules>
<!--用parent声明要继承的父工程的pom配置,即本工程的父工程坐标gav-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.9</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!--父工程的gavp-->
<groupId>com.fan</groupId>
<artifactId>yygh_parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!--packaging:项目打包的类型,一般父工程设置为pom,子工程设置为jar-->
<packaging>pom</packaging>
<name>yygh_parent</name>
<!--工程描述-->
<description>Demo project for Spring Boot</description>
<!--properties属性:使用自定义标签统一声明版本号-->
<properties>
<java.version>1.8</java.version>
<cloud.version>Hoxton.RELEASE</cloud.version>
<alibaba.version>2.2.0.RELEASE</alibaba.version>
<mybatis-plus.version>3.4.2</mybatis-plus.version>
<mysql.version>8.0.22</mysql.version>
<swagger.version>2.7.0</swagger.version>
<jwt.version>0.7.0</jwt.version>
<fastjson.version>1.2.29</fastjson.version>
<httpclient.version>4.5.1</httpclient.version>
<easyexcel.version>2.2.0-beta2</easyexcel.version>
<aliyun.version>4.1.1</aliyun.version>
<oss.version>3.9.1</oss.version>
<jodatime.version>2.10.1</jodatime.version>
</properties>
<!--配置dependencyManagement锁定依赖的版本,只是对版本进行管理,不会实际引入jar-->
<!--配置dependencyManagement锁定依赖的版本-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mybatis-plus 持久层-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<!--swagger ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>${aliyun.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${oss.version}</version>
</dependency>
<!--日期时间工具-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${jodatime.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<!-- 项目打包时会将java目录中的*.xml文件也进行打包 -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
2.在根父工程yygh_parent下搭建父模块common:
目标:
在父工程下创建子模块
子模块使用maven:
common
common的pom:
<?xml version="1.0" encoding="UTF-8"?>
<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>yygh_parent</artifactId>
<groupId>com.fan</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!--gavp,gv继承父工程的-->
<artifactId>common</artifactId>
<packaging>pom</packaging>
<modules>
<module>common_util</module>
<module>svervice_util</module>
</modules>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided </scope>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<scope>provided </scope>
</dependency>
<!--lombok用来简化实体类:需要安装lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
</project>
common子模块下继续创建2个子模块:
3.在根父工程yygh_parent下创建子模块model:
model的pom:
<?xml version="1.0" encoding="UTF-8"?>
<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>yygh_parent</artifactId>
<groupId>com.fan</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>model</artifactId>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<scope>provided </scope>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<scope>provided </scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<scope>provided </scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<scope>provided </scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<scope>provided </scope>
</dependency>
</dependencies>
</project>
4.在根父工程yygh_parent下创建父模块service:
service的pom:
<?xml version="1.0" encoding="UTF-8"?>
<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>yygh_parent</artifactId>
<groupId>com.fan</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service</artifactId>
<packaging>pom</packaging>
<modules>
<module>service_user</module>
</modules>
<dependencies>
<dependency>
<groupId>com.fan</groupId>
<artifactId>model</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.fan</groupId>
<artifactId>svervice_util</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--开发者工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- 服务调用feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 服务注册 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 流量控制 -->
<!-- <dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes> <include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
然后删掉yygh_parent,common,service的src,因为这几个都是父模块,并且不需要写代码
最终搭建的模块效果:
二、gitee使用:
1.gitee官网创建远程仓库:
复制远程地址:
2.idea中创建本地仓库:
VCS->Import into Version control–>Create Git Repository
3.提交代码到本地仓库:add+commit
4.提交到远程库:git–>push
远程库地址设置:
第一次推送,需要填写地址
将上面项目放到远程库即可;
三、医院设置需求:
1、需求
医院设置主要是用来保存开通医院的一些基本信息,每个医院一条信息,保存了医院编号(平台分配,全局唯一)和接口调用相关的签名key等信息,是整个流程的第一步,只有开通了医院设置信息,才可以上传医院相关信息。
我们所开发的功能就是基于单表的一个CRUD、锁定/解锁和发送签名信息这些基本功能。
2、表结构
创建表:我这里用mysql8.0.22,客户端是navicat
sql:数据自己添加
CREATE DATABASE IF NOT EXISTS `yygh_cmn` CHARACTER SET utf8;
USE `yygh_cmn`;
CREATE TABLE `hospital_set` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`hosname` varchar(100) DEFAULT NULL COMMENT '医院名称',
`hoscode` varchar(30) DEFAULT NULL COMMENT '医院编号',
`api_url` varchar(100) DEFAULT NULL COMMENT 'api基础路径',
`sign_key` varchar(50) DEFAULT NULL COMMENT '签名秘钥',
`contacts_name` varchar(20) DEFAULT NULL COMMENT '联系人',
`contacts_phone` varchar(11) DEFAULT NULL COMMENT '联系人手机',
`status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '状态',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`is_deleted` tinyint(3) NOT NULL DEFAULT '0' COMMENT '逻辑删除(1:已删除,0:未删除)',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hoscode` (`hoscode`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='医院设置表';
表字段的说明:
hosname:医院名称
hoscode:医院编号(平台分配,全局唯一,api接口必填信息)
api_url:医院回调的基础url(如:预约下单,我们要调用该地址去医院下单)
sign_key:双方api接口调用的签名key,有平台生成
contacts_name:医院联系人姓名
contacts_phone:医院联系人手机
status:状态(锁定/解锁)
四、医院模块开发
1.在service父模块下创建新的子模块:service_hosp
1.pom文件不需要修改:
2.配置文件application.properties:
# 服务端口
server.port=8201
# 服务名
spring.application.name=service-hosp
# 环境设置:dev、test、prod
spring.profiles.active=dev
# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatis_plus?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
#spring.data.mongodb.uri=mongodb://192.168.44.165:27017/yygh_hosp
# nacos服务地址
#spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#rabbitmq地址
#spring.rabbitmq.host=192.168.44.165
#spring.rabbitmq.port=5672
#spring.rabbitmq.username=guest
#spring.rabbitmq.password=guest
#配置mapper xml文件的路径
#mybatis-plus.mapper-locations=classpath:com/atguigu/yygh/mapper/xml/*.xml
#mybatis-plus.mapper-locations=classpath:com/atguigu/yygh/mapper/xml/*.xml
# nacos服务地址
#spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#开启sentinel
#feign.sentinel.enabled=true
#设置sentinel地址
#spring.cloud.sentinel.transport.dashboard=http://127.0.0.1:8858
#mongodb地址
#spring.data.mongodb.host=192.168.44.163
#spring.data.mongodb.port=27017
#spring.data.mongodb.database=yygh_hosp
#rabbitmq地址
#spring.rabbitmq.host=127.0.0.1
#spring.rabbitmq.port=5672
#spring.rabbitmq.username=guest
#spring.rabbitmq.password=guest
#logging.level.root=DEBUG
现阶段不用的配置先注释掉;
3.添加启动类:
手动创建这几个包和启动类:
ServiceHospApplication 启动类:
package com.fan.yygh.hosp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ServiceHospApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceHospApplication.class,args);
}
}
启动测试,记得注释掉service的pom中的服务调用的依赖,如下三个:
没有报错;ok;
2.医院设置的最终curd:
2.1 添加model实体类模块
说明:由于实体对象没有逻辑,我们已经统一导入
com.fan.yygh.model.hosp.HospitalSet
model模块放所有的实体类,为了统一管理所有的实体类。
说明:我们要把model模块引入到service父模块中,为了让service下所有的子模块都可以继承使用model中的实体类;这样我们就没有必要在service_hosp子模块下引入model模块了。
service的pom文件如下:
将资料中的com文件夹整个复制到src-java下即可:
2.2编写mapper:
添加com.fan.yygh.hosp.mapper.HospitalSetMapper
HospitalSetMapper 接口:
package com.fan.yygh.hosp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fan.yygh.model.hosp.HospitalSet;
public interface HospitalSetMapper extends BaseMapper<HospitalSet> {
}
创建xml文件夹和文件:
HospitalSetMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fan.yygh.hosp.mapper.HospitalSetMapper">
</mapper>
2.3添加service接口及实现类
HospitalSetService接口:
package com.fan.yygh.hosp.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.fan.yygh.model.hosp.HospitalSet;
public interface HospitalSetService extends IService<HospitalSet> {
}
impl:
实现类impl.HospitalSetServiceImpl:
package com.fan.yygh.hosp.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fan.yygh.hosp.mapper.HospitalSetMapper;
import com.fan.yygh.hosp.service.HospitalSetService;
import com.fan.yygh.model.hosp.HospitalSet;
import org.springframework.stereotype.Service;
@Service
public class HospitalSetServiceImpl extends
ServiceImpl<HospitalSetMapper, HospitalSet> implements
HospitalSetService {
}
2.4添加controller
HospitalSetController :
package com.fan.yygh.hosp.controller;
import com.fan.yygh.hosp.service.HospitalSetService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/admin/hosp/hospitalSet")
public class HospitalSetController {
//注入service接口
@Autowired
private HospitalSetService hospitalSetService;
}
最后效果:
2.5医院设置CRUD编写
由于com.baomidou.mybatisplus.extension.service.impl.ServiceImpl类已经默认实现 了单表的CRUD,分页查询也有默认实现,能够更加灵活和代码简洁把分页查询功能实现。
我们直接用service层的curd,这里是最终的controller:
@RestController
@RequestMapping("/admin/hosp/hospitalSet")
@Api("医院设置的控制器")
@CrossOrigin //解决跨域问题的
public class HospitalSetController {
//注入service接口
@Resource
private HospitalSetService hospitalSetService;
@GetMapping("findAll")
@ApiOperation(value = "findAllHospital查找所有")
public Result findAllHospital(){
List<HospitalSet> list = hospitalSetService.list();
return Result.ok(list);
}
@DeleteMapping("{id}")
@ApiOperation("逻辑删除")
public Result removeHospSet(@PathVariable Long id){
boolean b = hospitalSetService.removeById(id);
if(b){
return Result.ok();
}else{
return Result.fail();
}
}
//3.条件查询带分页
@PostMapping("findPageHospSet/{current}/{limit}")
public Result findPageHospSet(@PathVariable long current ,
@PathVariable long limit,
@RequestBody(required = false) HospitalSetQueryVo hospitalSetQueryVo
){
//创建page对象,传递当前页,每页的记录数
Page<HospitalSet> page = new Page<>(current, limit);
//构造条件
QueryWrapper<HospitalSet> hospitalSetQueryWrapper = new QueryWrapper<>();
String hosname = hospitalSetQueryVo.getHosname();//医院名称
String hoscode = hospitalSetQueryVo.getHoscode();//医院编号
if(!StringUtils.isEmpty(hosname)){
hospitalSetQueryWrapper.like("hosname",hospitalSetQueryVo.getHosname());
}
if(!StringUtils.isEmpty(hoscode)){
hospitalSetQueryWrapper.eq("hoscode",hospitalSetQueryVo.getHoscode());
}
//调用方法实现分页查询
Page<HospitalSet> hospitalSetPage = hospitalSetService.page(page, hospitalSetQueryWrapper);
return Result.ok(hospitalSetPage);
}
//4.添加医院设置,@RequestBody主要用来接收前端传递给后端的json字符串中的数据的
@PostMapping("saveHospSet")
public Result saveHospSet(@RequestBody(required = true) HospitalSet hospitalSet){
//手动设置状态,1使用,0表示不能使用
hospitalSet.setStatus(1);
//签名秘钥
Random random = new Random();
hospitalSet.setSignKey(MD5.encrypt(System.currentTimeMillis()+""+
random.nextInt(1000)));
//调用保存方法
boolean b = hospitalSetService.save(hospitalSet);
if(b){
return Result.ok();
}else{
return Result.fail();
}
}
//5.根据id获取医院设置 信息
@GetMapping("getHospSet/{id}")
public Result<HospitalSet> getHospSet(@PathVariable Long id ){
/*try {
int a = 1/0;
} catch (Exception e) {
throw new YyghException("失败",201);//爆出自定义异常
}*/
HospitalSet byId = hospitalSetService.getById(id);
return Result.ok(byId);
}
//6.修改医院设置的接口
@PostMapping("/updateHospSet") //@RequestBody获取前端封装的参数
public Result updateHospSet(@RequestBody HospitalSet hospitalSet){
//修改的话应该更新 修改时间
hospitalSet.setUpdateTime(new Date());
boolean b = hospitalSetService.updateById(hospitalSet);
if(b){
return Result.ok();
}else{
return Result.fail();
}
}
//7.批量删除 医院设置的接口
@DeleteMapping("batchRemove")
public Result batchRemove(@RequestBody List<Long> idList){
boolean b = hospitalSetService.removeByIds(idList);
return Result.ok();
}
//@PutMapping 更新请求
/*
* 如果执行添加操作, 后面的添加请求不会覆盖前面的请求, 所以使用@Postmapping
如果执行修改操作, 后面的修改请求会把前面的请求给覆盖掉, 所以使用@PutMapping*/
//8 医院设置锁定和解锁
@PutMapping("lockHospitalSet/{id}/{status}")
public Result lockHospitalSet(@PathVariable Long id,
@PathVariable Integer status) {
//根据id查询医院设置信息
HospitalSet hospitalSet = hospitalSetService.getById(id);
//设置状态
hospitalSet.setStatus(status);
//调用方法
hospitalSetService.updateById(hospitalSet);
return Result.ok();
}
//9 发送签名秘钥
@PutMapping("sendKey/{id}")
public Result lockHospitalSet(@PathVariable Long id) {
HospitalSet hospitalSet = hospitalSetService.getById(id);
String signKey = hospitalSet.getSignKey();
String hoscode = hospitalSet.getHoscode();
//TODO 发送短信
return Result.ok();
}
}
简单测试controller:
package com.fan.yygh.hosp.controller;
import com.fan.yygh.hosp.service.HospitalSetService;
import com.fan.yygh.model.hosp.HospitalSet;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/admin/hosp/hospitalSet")
@Api("医院设置的控制器")
public class HospitalSetController {
//注入service接口
@Autowired
private HospitalSetService hospitalSetService;
@GetMapping("findAll")
@ApiOperation(value = "findAllHospital查找所有")
public List<HospitalSet> findAllHospital(){
List<HospitalSet> list = hospitalSetService.list();
return list;
}
}
我这里直接使用swagger:config的swagger配置类:
package com.fan.yygh.hosp.config;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @Author: zq
* @Date 2020-08-24 10:55
* @Description swagger 配置类,swagger基本信息和接口的权限
* @ClassName SwaggerConfig
* @PackageName com.zq.springboot.common.config
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
/**
* 创建api实例
* @return
*/
@Bean
public Docket createRestAoi(){
return new Docket(DocumentationType.SWAGGER_2)
//用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
.apiInfo(apiInfo())
//设置哪些接口暴露给Swagger展示
.select()
//扫描所有有注解的api,用这种方式更灵活,指定为ApiOperation.class
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
//构建
.build();
}
/**
* 添加摘要信息
* @return
*/
private ApiInfo apiInfo(){
//用ApiInfoBuilder进行定制,可以设置不同的属性,比较方便
return new ApiInfoBuilder()
//设置标题
.title("标题:springboot集成swagger测试")
//描述
.description("描述:用于测试集成swagger接口")
//作者信息
.contact(new Contact("zq",null,null))
//版本
.version("版本号:1.0")
//构建
.build();
}
}
1.如果使用了springboot2.6.9,需要增加这个配置:
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
2.注意换成自己的数据库:yygh_cmn
# 服务端口
server.port=8201
# 服务名
spring.application.name=service-hosp
# 环境设置:dev、test、prod
spring.profiles.active=dev
# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/yygh_cmn?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
#spring.data.mongodb.uri=mongodb://192.168.44.165:27017/yygh_hosp
# nacos服务地址
#spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#rabbitmq地址
#spring.rabbitmq.host=192.168.44.165
#spring.rabbitmq.port=5672
#spring.rabbitmq.username=guest
#spring.rabbitmq.password=guest
#配置mapper xml文件的路径
#mybatis-plus.mapper-locations=classpath:com/atguigu/yygh/mapper/xml/*.xml
#mybatis-plus.mapper-locations=classpath:com/atguigu/yygh/mapper/xml/*.xml
# nacos服务地址
#spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#开启sentinel
#feign.sentinel.enabled=true
#设置sentinel地址
#spring.cloud.sentinel.transport.dashboard=http://127.0.0.1:8858
#mongodb地址
#spring.data.mongodb.host=192.168.44.163
#spring.data.mongodb.port=27017
#spring.data.mongodb.database=yygh_hosp
#rabbitmq地址
#spring.rabbitmq.host=127.0.0.1
#spring.rabbitmq.port=5672
#spring.rabbitmq.username=guest
#spring.rabbitmq.password=guest
#logging.level.root=DEBUG
mapper可以加启动类上,也可以加在配置类上,建议放在配置类上
逻辑删除:
3.工具类swagger:
先在common模块pom.xml引入依赖springfox-swagger2
然后将swagger配置类Swagger2Config放到common父模块下的service_util模块下:
com.fan.yygh.common.config.Swagger2Config:
使用资料中给的swagger配置类:
package com.fan.yygh.common.config;
import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger2配置信息
*/
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket webApiConfig(){
return new Docket(DocumentationType.SWAGGER_2)
.groupName("webApi")
.apiInfo(webApiInfo())
.select()
//只显示api路径下的页面
.paths(Predicates.and(PathSelectors.regex("/api/.*")))
.build();
}
@Bean
public Docket adminApiConfig(){
return new Docket(DocumentationType.SWAGGER_2)
.groupName("adminApi")
.apiInfo(adminApiInfo())
.select()
//只显示admin路径下的页面
.paths(Predicates.and(PathSelectors.regex("/admin/.*")))
.build();
}
private ApiInfo webApiInfo(){
return new ApiInfoBuilder()
.title("网站-API文档")
.description("本文档描述了网站微服务接口定义")
.version("1.1")
.contact(new Contact("fan", "http://atguigu.com", "493211102@qq.com"))
.build();
}
private ApiInfo adminApiInfo(){
return new ApiInfoBuilder()
.title("后台管理系统-API文档")
.description("本文档描述了后台管理系统微服务接口定义")
.version("1.1")
.contact(new Contact("fan", "http://atguigu.com", "49321112@qq.com"))
.build();
}
}
然后在启动类上增加@ComponentScan(basePackages = “com.fan”)
让其能扫描到swagger:
增加swagger标签:
swagger2:访问地址:http://localhost:8201/swagger-ui.html
4.SpringBoot统一返回result结果集
在使用SpringBoot项目多人开发时,返回给前端的数据类型如果不统一的话,会带来很多麻烦。这时,我们就应该规定一下约束,比如说统一返回的result结果集
改造controller中的请求方法的返回值:
5.条件查询带分页:
//3.条件查询带分页
@PostMapping("findPageHospSet/{current}/{limit}")
public Result findPageHospSet(@PathVariable long current ,
@PathVariable long limit,
@RequestBody(required = false) HospitalSetQueryVo hospitalSetQueryVo){
//创建page对象,传递当前页,每页的记录数
Page<HospitalSet> page = new Page<>(current, limit);
//构造条件
QueryWrapper<HospitalSet> hospitalSetQueryWrapper = new QueryWrapper<>();
String hosname = hospitalSetQueryVo.getHosname();//医院名称
String hoscode = hospitalSetQueryVo.getHoscode();//医院编号
if(!StringUtils.isEmpty(hosname)){
hospitalSetQueryWrapper.like("hosname",hospitalSetQueryVo.getHosname());
}
if(!StringUtils.isEmpty(hoscode)){
hospitalSetQueryWrapper.eq("hoscode",hospitalSetQueryVo.getHoscode());
}
//调用方法实现分页查询
Page<HospitalSet> hospitalSetPage = hospitalSetService.page(page, hospitalSetQueryWrapper);
return Result.ok(hospitalSetPage);
}
注意:这里可以使用Integer类型的:
@PathVariable Integer current,
@PathVariable Integer limit
添加医院设置:
测试数据:
{
"apiUrl": "http:localhost:9999",
"contactsName": "张三",
"contactsPhone": "123",
"hoscode": "1000_1",
"hosname": "深圳人民医院",
"isDeleted": 0
}
修改的参数:
删除参数:
6.医院设置锁定和解锁和发送签名秘钥
在HospitalSetController类添加方法
//8.医院设置锁定和解锁
@PutMapping("lockHospitalSet/{id}/{status}")
public Result lockHospSet(@PathVariable Long id ,
@PathVariable Integer status){
//根据id查询医院设置信息
HospitalSet hospitalSet = hospitalSetService.getById(id);
//设置状态
hospitalSet.setStatus(status);
hospitalSetService.updateById(hospitalSet);//状态设置完毕后根据id更新
return Result.ok();
}
//9 发送签名秘钥
@PutMapping("sendKey/{id}")
public Result lockHospitalSet(@PathVariable Long id) {
HospitalSet hospitalSet = hospitalSetService.getById(id);
String signKey = hospitalSet.getSignKey();
String hoscode = hospitalSet.getHoscode();
//TODO 发送短信
return Result.ok();
}
统一异常处理:
@ControllerAdvice注解是Spring3.2中新增的注解,学名是Controller增强器,作用是给Controller控制器添加统一的操作或处理。
对于@ControllerAdvice,我们比较熟知的用法是结合@ExceptionHandler用于全局异常的处理,但其作用不止于此。ControllerAdvice拆开来就是Controller Advice,关于Advice,在Spring的AOP中,是用来封装一个切面所有属性的,包括切入点和需要织入的切面逻辑。这里ControllerAdvice也可以这么理解,
其抽象级别应该是用于对Controller进行切面环绕的,而具体的业务织入方式则是通过结合其他的注解来实现的。@ControllerAdvice是在类上声明的注解,其用法主要有三点:
1.结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的。
2.结合方法型注解@InitBinder,用于request中自定义参数解析方式进行注册,从而达到自定义指定格式参数的目的。
3.结合方法型注解@ModelAttribute,表示其注解的方法将会在目标Controller方法执行之前执行。
从上面的讲解可以看出,@ControllerAdvice的用法基本是将其声明在某个bean上,然后在该bean的方法上使用其他的注解来指定不同的织入逻辑。不过这里@ControllerAdvice并不是使用AOP的方式来织入业务逻辑的,而是Spring内置对其各个逻辑的织入方式进行了内置支持
自定义异常:
我们在搭建模块时在common-util模块已经添加了YyghException类:
package com.fan.yygh.common.exception;
import com.fan.yygh.common.result.ResultCodeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 自定义全局异常类
*
* @author qy
*/
@Data
@ApiModel(value = "自定义全局异常类")
public class YyghException extends RuntimeException {
@ApiModelProperty(value = "异常状态码")
private Integer code;
/**
* 通过状态码和错误消息创建异常对象
* @param message
* @param code
*/
public YyghException(String message, Integer code) {
super(message);
this.code = code;
}
/**
* 接收枚举类型对象
* @param resultCodeEnum
*/
public YyghException(ResultCodeEnum resultCodeEnum) {
super(resultCodeEnum.getMessage());
this.code = resultCodeEnum.getCode();
}
@Override
public String toString() {
return "YyghException{" +
"code=" + code +
", message=" + this.getMessage() +
'}';
}
}
修改这个:
添加全局异常处理类
在service-util模块添加全局异常处理类
全局异常:
package com.fan.yygh.common.exception;
import com.fan.yygh.common.result.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Result error(Exception e){
e.printStackTrace();
return Result.fail();
}
@ExceptionHandler(YyghException.class)
public Result error2(Exception e){
e.printStackTrace();
return Result.fail();
}
}
模拟异常并测试:
统一日志处理:
日志xml中输出地址:修改成这样:
value=“D:\yygh_log\edu”
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<contextName>logback</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<property name="log.path" value="D:\\yygh_log\\edu" />
<!-- 彩色日志 -->
<!-- 配置格式变量:CONSOLE_LOG_PATTERN 彩色日志格式 -->
<!-- magenta:洋红 -->
<!-- boldMagenta:粗红-->
<!-- cyan:青色 -->
<!-- white:白色 -->
<!-- magenta:洋红 -->
<property name="CONSOLE_LOG_PATTERN"
value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/>
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<!-- 例如:如果此处配置了INFO级别,则后面其他位置即使配置了DEBUG级别的日志,也不会被输出 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--输出到文件-->
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_warn.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。
<logger>仅有一个name属性,
一个可选的level和一个可选的addtivity属性。
name:用来指定受此logger约束的某一个包或者具体的某一个类。
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
如果未设置此属性,那么当前logger将会继承上级的级别。
-->
<!--
使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
第一种把<root level="INFO">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
第二种就是单独给mapper下目录配置DEBUG模式,代码如下,这样配置sql语句会打印,其他还是正常DEBUG级别:
-->
<!--开发环境:打印控制台-->
<springProfile name="dev">
<!--可以输出项目中的debug日志,包括mybatis的sql日志-->
<logger name="com.guli" level="INFO" />
<!--
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认是DEBUG
可以包含零个或多个appender元素。
-->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</springProfile>
<!--生产环境:输出到文件-->
<springProfile name="pro">
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="ERROR_FILE" />
<appender-ref ref="WARN_FILE" />
</root>
</springProfile>
</configuration>