4.java项目-尚医通(4)

代码参考:https://github.com/wyj41/yygh_parent.git

MongoDB

1. MongoDB简介

1.1 NoSQL简介

NoSQL(NoSQL = Not Only SQL),意即反SQL运动,指的是非关系型的数据库,是一项全新的数据库革命性运动,早期就有人提出,发展至2009年趋势越发高涨。NoSQL的拥护者们提倡运用非关系型的数据存储,相对于目前铺天盖地的关系型数据库运用,这一概念无疑是一种全新的思维的注入

为什么使用NoSQL :
1、对数据库高并发读写。
2、对海量数据的高效率存储和访问。
3、对数据库的高可扩展性和高可用性。

弱点:
1、数据库事务一致性需求
2、数据库的写实时性和读实时性需求
3、对复杂的SQL查询,特别是多表关联查询的需求

1.2 什么是MongoDB ?

MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。

在高负载的情况下,添加更多的节点,可以保证服务器性能。

MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。

MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。

1.3 MongoDB 特点

1、MongoDB 是一个面向文档存储的数据库,操作起来比较简单和容易。
2、你可以在MongoDB记录中设置任何属性的索引 (如:FirstName=“Sameer”,Address=“8 Gandhi Road”)来实现更快的排序。
3、你可以通过本地或者网络创建数据镜像,这使得MongoDB有更强的扩展性。
4、如果负载的增加(需要更多的存储空间和更强的处理能力) ,它可以分布在计算机网络中的其他节点上这就是所谓的分片。
5、Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。
6、MongoDb 使用update()命令可以实现替换完成的文档(数据)或者一些指定的数据字段 。
7、Mongodb中的Map/reduce主要是用来对数据进行批量处理和聚合操作。
8、Map和Reduce。Map函数调用emit(key,value)遍历集合中所有的记录,将key与value传给Reduce函数进行处理。
9、Map函数和Reduce函数是使用Javascript编写的,并可以通过db.runCommand或mapreduce命令来执行MapReduce操作。
10、GridFS是MongoDB中的一个内置功能,可以用于存放大量小文件。
11、MongoDB允许在服务端执行脚本,可以用Javascript编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。
12、MongoDB支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。
13、MongoDB安装简单。

1.4 安装MongoDB

1.4.1 方式一:安装docker镜像

debian安装docker

apt-get update

#安装依赖项
apt install apt-transport-https ca-certificates curl software-properties-common gnupg2

#使用以下 curl 命令导入存储库的 GPG 密钥
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -

#将 Docker APT 存储库添加到系统的软件存储库列表中
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"

#更新apt
apt-get update

#确保要从Docker repo而不是默认的Debian repo安装
apt-cache policy docker-ce

#安装最新版本的 Docker CE (Community Edition)
apt install docker-ce

#安装完成后, Docker 服务将自动启动。您可以输入以下命令进行验证
systemctl status docker

#查看docker的版本
docker -v

docker换源

 vim /etc/docker/daemon.json

#输入以下内容:
{
    "registry-mirrors": [
        "https://9gjy9gk8.mirror.aliyuncs.com",
        "https://hub-mirror.c.163.com",
        "https://mirror.baidubce.com"
    ]
}

#重启docker服务使配置生效
systemctl daemon-reload
systemctl restart docker.service

#查看配置是否成功
docker info

#出现以下内容说明配置成功
 Registry Mirrors:
  https://9gjy9gk8.mirror.aliyuncs.com/
  https://hub-mirror.c.163.com/
  https://mirror.baidubce.com/

安装MongoDB

#拉取镜像 
docker pull mongo:latest

#创建和启动容器 
docker run -d --restart=always -p 27017:27017 --name mymongo -v /data/db:/data/db -d mongo

#进入容器 
docker exec -it mymongo /bin/bash 

#使用MongoDB客户端进行操作 
mongo 

> show dbs #查询所有的数据库
1.4.2 方式二:直接在debian上安装MongoDB

安装MongoDB

# 安装添加新存储库所需的软件包
apt install dirmngr gnupg apt-transport-https software-properties-common ca-certificates curl

# 将MongoDB GPG密钥添加到系统
curl -fsSL https://www.mongodb.org/static/pgp/server-4.2.asc | sudo apt-key add -

# 启用MongoDB存储库
add-apt-repository 'deb https://repo.mongodb.org/apt/debian buster/mongodb-org/4.2 main'

# 更新软件包列表并安装mongodb-org元软件包
apt update
apt install mongodb-org

# 启动MongoDB服务,并使其在启动时启动
systemctl enable mongod --now

# 要验证安装是否成功完成,请使用该mongo工具连接到MongoDB数据库服务器并打印连接状态
mongo --eval 'db.runCommand({ connectionStatus: 1 })'

# 输出内容中ok字段1表示成功

配置MongoDB
MongoDB配置文件已命名mongod.conf并位于/etc目录中。该文件为YAML格式。

开启远程访问

vim /etc/mongod.conf

#并注释 bindIp: 127.0.0.1

编辑配置文件后,重新启动mongod服务以使更改生效:

systemctl restart mongod

1.5 MongoDB 概念解析

不管我们学习什么数据库都应该学习其中的基础概念,在mongodb中基本的概念是文档、集合、数据库,下面我们挨个介绍。

下表将帮助您更容易理解Mongo中的一些概念:

SQL术语/概念MongoDB术语/概念解释/说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据记录行/文档
columnfield数据字段/域
indexindex索引
table joins表连接,MongoDB不支持
primarykeyprimary key

1.6 数据库

一个mongodb中可以建立多个数据库
常用操作

1、 Help查看命令提示 
db.help();

2、 切换/创建数据库
use test

如果数据库不存在,则创建数据库,否则切换到指定数据库

3、 查询所有数据库 
show dbs;

4、 删除当前使用数据库 
db.dropDatabase();

5、 查看当前使用的数据库 
db.getName();

6、 显示当前db状态 
db.stats();

7、 当前db版本 
db.version();

8、 查看当前db的链接机器地址 
db.getMongo();

1.7 文档

文档是一组键值(key-value)对(即BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。

下表列出了 RDBMS 与 MongoDB 对应的术语:

RDBMSMongoDB
数据库数据库
表格集合
文档
字段
表联合嵌入文档
主键主键 (MongoDB 提供了 key 为 _id )

需要注意的是:
1、文档中的键/值对是有序的。
2、文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
3、MongoDB区分类型和大小写。
4、MongoDB的文档不能有重复的键。
5、文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。

文档键命名规范:
1、键不能含有\0 (空字符)。这个字符用来表示键的结尾。
2、.和$有特别的意义,只有在特定环境下才能使用。
3、以下划线"_"开头的键是保留的(不是严格要求的)。

1.8 集合

集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中的表格。
集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。

常用命令:

1、 创建一个集合(table)
db.createCollection( "collName");

2、 得到指定名称的集合(table )
db.getCollection("user");

1.9 MongoDB 数据类型

下表为MongoDB中常用的几种数据类型:

数据类型描述
String字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。
Integer整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。
Boolean布尔值。用于存储布尔值(真/假)。
Double双精度浮点值。用于存储浮点值。
Min/Max keys将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。
Arrays用于将数组或列表或多个值存储为一个键。
Timestamp时间戳。记录文档修改或添加的具体时间。
Object用于内嵌文档。
Null用于创建空值。
Symbol符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。
Date日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。
Object ID对象 ID。用于创建文档的 ID。
Binary Data二进制数据。用于存储二进制数据。
Code代码类型。用于在文档中存储 JavaScript 代码。
Regular expression正则表达式类型。用于存储正则表达式。

1.10 适用场景

适用场景
1、网站数据:Mongo非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
2、缓存:由于性能很高,Mongo也适合作为信息基础设施的缓存层。在系统重启之后,由M ongo搭建的持久化缓存层可以避免下层的数据源过载。
3、大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵, 在此之前,很多时候程序员往往会选择传统的文件进行存储。
4、高伸缩性的场景:Mongo非常适合由数十或数百台服务器组成的数据库。Mongo的路线图中已经包含对Map Reduce弓摩的内置支持。
5、用于对象及 JSON数据的存储:Mongo的BSON数据格式非常适合文档化格式的存储 及查询。

不适用场合
1、高度事务性的系统:例如银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。
2、传统的商业智能应用:针对特定问题的BI数据库会对产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择。

1.11 常用操作

INSERT

db.User.save({name:'zhangsan',age:21,sex:true})
db.User.find()

Query

# WHERE
# select * from User where name = 'zhangsan'
db.User.find({name:"zhangsan"})

# FIELDS
# select name, age from User where age = 21
db.User.find({age:21}, {'name':1, 'age':1})

# SORT
# select * from User order by age
db.User.find().sort({age:1})

# SUCE
# select * from User skip 2 limit 3
db.User.find().skip(0).limit(3)

# IN
# select * from User where age in (21, 26, 32)
db.User.find({age:{$in:[21,26,32]}})

# COUNT
# select count(*) from User where age >20
db.User.find({age:{$gt:20}}).count()

# 0R
# select * from User where age = 21 or age = 28
db.User.find({$or:[{age:21}, {age:28}]})

Update

# update Userset age = 100, sex = 0 where name = 'user1'
db.User.update({name:"zhangsan"}, {$set:{age:100, sex:0}})

Remove

db.User.remove(id)
//移除对应id的行

db.User.remove({})
//移除所有

常见的聚合表达式

表达式描述实例
$sum计算总和db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { s u m : " sum : " sum:"likes"}}}])
$avg计算平均值db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { a v g : " avg : " avg:"likes"}}}])
$min获取集合中所有文档对应值得最小值db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { m i n : " min : " min:"likes"}}}])
$max获取集合中所有文档对应值得最大值。db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { m a x : " max : " max:"likes"}}}])
$push在结果文档中插入值到一个数组中。db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", url : { p u s h : " push: " push:"url"}}}])
$addToSet在结果文档中插入值到一个数组中,但不创建副本。db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", url : { a d d T o S e t : " addToSet : " addToSet:"url"}}}])
$first根据资源文档的排序获取第一个文档数据。db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", first_url : { f i r s t : " first : " first:"url"}}}])
$last根据资源文档的排序获取最后一个文档数据db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", last_url : { l a s t : " last : " last:"url"}}}])

索引
索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。

db.User.createIndex({"name":1})

语法中 name值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可

2.Spring boot集成mongodb

2.1 集成简介

spring-data-mongodb提供了MongoTemplate与MongoRepository两种方式访问mongodb,MongoRepository操作简单,MongoTemplate操作灵活,我们在项目中可以灵活适用这两种方式操作mongodb,MongoRepository的缺点是不够灵活,MongoTemplate正好可以弥补不足。

2.2 搭建开发环境

创建springboot工程

添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>2.10.1</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

添加配置
在application.yml文件添加配置

spring:
  data:
    mongodb:
      uri: mongodb://192.168.50.224:27017/test
      auto-index-creation: false

2.3 基于MongoTemplate 开发CRUD

添加实体类

package com.myproject;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Data
@Document("User")
public class User {

    @Id
    private String id;
    private String name;
    private Integer age;
    private String email;
    private String createDate;
}

实现
常用方法
mongoTemplate.findAll(User.class): 查询User文档的全部数据
mongoTemplate.findById(, User.class): 查询User文档id为id的数据
mongoTemplate.find(query, User.class);: 根据query内的查询条件查询
mongoTemplate.upsert(query, update, User.class): 修改
mongoTemplate.remove(query, User.class): 删除
mongoTemplate.insert(User): 新增

Query对象
1、创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)
2、 精准条件:criteria.and(“key”).is(“条件”)
模糊条件:criteria.and(“key”).regex(“条件”)
3、封装条件:query.addCriteria(criteria)
4、大于(创建新的criteria):Criteria gt = Criteria.where(“key”).gt(“条件”)
小于(创建新的criteria):Criteria lt = Criteria.where(“key”).lt(“条件”)
5、Query.addCriteria(new Criteria().andOperator(gt,lt));
6、一个query中只能有一个andOperator()。其参数也可以是Criteria数组。
7、排序 :query.with(new Sort(Sort.Direction.ASC, “age”). and(new Sort(Sort.Direction.DESC, “date”)))

添加测试类
在test/java下添加测试类

package com.myproject;

import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

@SpringBootTest
class MongodbDemoApplicationTests {

    @Autowired
    private MongoTemplate mongoTemplate;

    //添加
    @Test
    public void createUser() {
        User user = new User();
        user.setAge(20);
        user.setName("test");
        user.setEmail("4932200@qq.com");
        User user1 = mongoTemplate.insert(user);
        System.out.println(user1);
    }

    //查询所有
    @Test
    public void findUser() {
        List<User> userList = mongoTemplate.findAll(User.class);
        System.out.println(userList);
    }

    //根据id查询
    @Test
    public void getById() {
        User user =
                mongoTemplate.findById("62da4e1422dfd40e5672b435", User.class);
        System.out.println(user);
    }

    //条件查询
    @Test
    public void findUserList() {
        Query query = new Query(Criteria
                .where("name").is("test")
                .and("age").is(20));
        List<User> userList = mongoTemplate.find(query, User.class);
        System.out.println(userList);
    }

    //模糊查询
    @Test
    public void findUsersLikeName() {
        String name = "est";
        String regex = String.format("%s%s%s", "^.*", name, ".*$");
        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        Query query = new Query(Criteria.where("name").regex(pattern));
        List<User> userList = mongoTemplate.find(query, User.class);
        System.out.println(userList);
    }

    //分页查询
    @Test
    public void findUsersPage() {
        String name = "est";
        int pageNo = 1;
        int pageSize = 10;

        Query query = new Query();
        String regex = String.format("%s%s%s", "^.*", name, ".*$");
        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        query.addCriteria(Criteria.where("name").regex(pattern));
        int totalCount = (int) mongoTemplate.count(query, User.class);
        List<User> userList = mongoTemplate.find(query.skip((pageNo - 1) * pageSize).limit(pageSize), User.class);

        Map<String, Object> pageMap = new HashMap<>();
        pageMap.put("list", userList);
        pageMap.put("totalCount",totalCount);
        System.out.println(pageMap);
    }

    //修改
    @Test
    public void updateUser() {
        User user = mongoTemplate.findById("62da4e1422dfd40e5672b435", User.class);
        user.setName("test_1");
        user.setAge(25);
        user.setEmail("493220990@qq.com");
        Query query = new Query(Criteria.where("_id").is(user.getId()));
        Update update = new Update();
        update.set("name", user.getName());
        update.set("age", user.getAge());
        update.set("email", user.getEmail());
        UpdateResult result = mongoTemplate.upsert(query, update, User.class);
        long count = result.getModifiedCount();
        System.out.println(count);
    }

    //删除操作
    @Test
    public void delete() {
        Query query =
                new Query(Criteria.where("_id").is("62da4e1422dfd40e5672b435"));
        DeleteResult result = mongoTemplate.remove(query, User.class);
        long count = result.getDeletedCount();
        System.out.println(count);
    }

}

2.4 基于MongoRepository开发CRUD

Spring Data提供了对mongodb数据访问的支持,我们只需要继承MongoRepository类,按照Spring Data规范就可以了

SpringData 方法定义规范:
1、不是随便声明的,而需要符合一定的规范
2、 查询方法以find | read | get开头
3、 涉及条件查询时,条件的属性用条件关键字连接
4、 要注意的是:条件属性首字母需要大写
5、 支持属性的级联查询,但若当前类有符合条件的属性则优先使用,而不使用级联属性,若需要使用级联属性,则属性之间使用_强制进行连接

添加Repository类
在/test/java下面添加测试类:

package com.myproject;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.*;

import java.util.List;

@SpringBootTest
class DemomogoApplicationTests1 {

    @Autowired
    private UserRepository userRepository;

    //添加
    @Test
    public void createUser() {
        User user = new User();
        user.setAge(20);
        user.setName("张三");
        user.setEmail("3332200@qq.com");
        User user1 = userRepository.save(user);
    }

    //查询所有
    @Test
    public void findUser() {
        List<User> userList = userRepository.findAll();
        System.out.println(userList);
    }

    //id查询
    @Test
    public void getById() {
        User user = userRepository.findById("62da51d2e07d534424feecf7").get();
        System.out.println(user);
    }

    //条件查询
    @Test
    public void findUserList() {
        User user = new User();
        user.setName("张三");
        user.setAge(20);
        Example<User> userExample = Example.of(user);
        List<User> userList = userRepository.findAll(userExample);
        System.out.println(userList);
    }

    //模糊查询
    @Test
    public void findUsersLikeName() {
        //创建匹配器,即如何使用查询条件
        ExampleMatcher matcher = ExampleMatcher.matching() //构建对象
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //改变默认字符串匹配方式:模糊查询
                .withIgnoreCase(true); //改变默认大小写忽略方式:忽略大小写
        User user = new User();
        user.setName("三");
        Example<User> userExample = Example.of(user, matcher);
        List<User> userList = userRepository.findAll(userExample);
        System.out.println(userList);
    }

    //分页查询
    @Test
    public void findUsersPage() {
        Sort sort = Sort.by(Sort.Direction.DESC, "age");
        //0为第一页
        Pageable pageable = PageRequest.of(0, 10, sort);
        //创建匹配器,即如何使用查询条件
        ExampleMatcher matcher = ExampleMatcher.matching() //构建对象
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //改变默认字符串匹配方式:模糊查询
                .withIgnoreCase(true); //改变默认大小写忽略方式:忽略大小写
        User user = new User();
        user.setName("三");
        Example<User> userExample = Example.of(user, matcher);
        //创建实例
        Example<User> example = Example.of(user, matcher);
        Page<User> pages = userRepository.findAll(example, pageable);
        System.out.println(pages);
    }

    //修改
    @Test
    public void updateUser() {
        User user = userRepository.findById("62da51d2e07d534424feecf7").get();
        user.setName("张三_1");
        user.setAge(25);
        user.setEmail("883220990@qq.com");
        User save = userRepository.save(user);
        System.out.println(save);
    }

    //删除
    @Test
    public void delete() {
        userRepository.deleteById("62da51d2e07d534424feecf7");
    }
}

3.医院接口

需要用到的资料(链接:https://pan.baidu.com/s/1nO5gwcKLebhf11GBg73kMQ 提取码:w3ps)
参考《尚医通API接口文档.docx》业务接口4.1上传医院
参考《医院接口模拟系统.docx》进行接口测试与数据上传

准备工作

  1. 创建spring项目hospital_manage,导入整个项目
    记得修改mysql连接的服务器ip,账号,密码

  2. 创建数据库和表

# Host: localhost  (Version 5.7.19-log)
# Date: 2020-07-31 14:28:31
# Generator: MySQL-Front 6.1  (Build 1.26)

CREATE DATABASE IF NOT EXISTS `yygh_manage` CHARACTER SET utf8mb4;
USE `yygh_manage`;

#
# Structure for table "hospital_set"
#

CREATE TABLE `hospital_set` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `hoscode` varchar(30) DEFAULT NULL COMMENT '医院编号',
  `sign_key` varchar(50) DEFAULT NULL COMMENT '签名秘钥',
  `api_url` varchar(100) DEFAULT NULL COMMENT '统一挂号平台api地址',
  `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`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='医院设置表';

#
# Structure for table "order_info"
#

CREATE TABLE `order_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `schedule_id` bigint(20) DEFAULT NULL COMMENT '排班id',
  `patient_id` bigint(20) DEFAULT NULL COMMENT '就诊人id',
  `number` int(11) DEFAULT NULL COMMENT '预约号序',
  `fetch_time` varchar(50) DEFAULT NULL COMMENT '建议取号时间',
  `fetch_address` varchar(255) DEFAULT NULL COMMENT '取号地点',
  `amount` decimal(10,0) DEFAULT NULL COMMENT '医事服务费',
  `pay_time` datetime DEFAULT NULL COMMENT '支付时间',
  `quit_time` datetime DEFAULT NULL COMMENT '退号时间',
  `order_status` tinyint(3) DEFAULT NULL 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`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT='订单表';

#
# Structure for table "schedule"
#

CREATE TABLE `schedule` (
  `id` bigint(20) NOT NULL DEFAULT '0' COMMENT '编号',
  `hoscode` varchar(30) DEFAULT NULL COMMENT '医院编号',
  `depcode` varchar(30) DEFAULT NULL COMMENT '科室编号',
  `title` varchar(20) DEFAULT NULL COMMENT '职称',
  `docname` varchar(20) DEFAULT NULL COMMENT '医生名称',
  `skill` text COMMENT '擅长技能',
  `work_date` date DEFAULT NULL COMMENT '安排日期',
  `work_time` tinyint(3) DEFAULT '0' COMMENT '安排时间(0:上午 1:下午)',
  `reserved_number` int(11) DEFAULT '0' COMMENT '可预约数',
  `available_number` int(11) DEFAULT '0' COMMENT '剩余预约数',
  `amount` decimal(10,0) DEFAULT NULL COMMENT '挂号费',
  `status` tinyint(3) DEFAULT NULL COMMENT '排班状态(-1:停诊 0:停约 1:可约)',
  `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`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='医生日程安排表';

#导入一条测试数据
USE yygh_manage;
INSERT INTO hospital_set
(id,hoscode,sign_key,api_url)
VALUES(1,'1000_0','44e469eddec16c551ca61525f04b0996','http://localhost:8201');

USE yygh_hosp;
INSERT INTO `hospital_set`
(`hosname`,`hoscode`,`api_url`,`sign_key`,`contacts_name`,`contacts_phone`)
VALUES("北京协和医院","1000_0","http://localhost:8201","44e469eddec16c551ca61525f04b0996","张三","18769658426");

  1. 启动hospital_manage项目,访问:http://localhost:9998/

  2. 在service_util模块下添加工具类
    com.myproject.yygh.common.utils.HttpUtil

package com.myproject.yygh.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 *
 */
@Slf4j
public final class HttpUtil {

    static final String POST = "POST";
    static final String GET = "GET";
    static final int CONN_TIMEOUT = 30000;// ms
    static final int READ_TIMEOUT = 30000;// ms

    /**
     * post 方式发送http请求.
     *
     * @param strUrl
     * @param reqData
     * @return
     */
    public static byte[] doPost(String strUrl, byte[] reqData) {
        return send(strUrl, POST, reqData);
    }

    /**
     * get方式发送http请求.
     *
     * @param strUrl
     * @return
     */
    public static byte[] doGet(String strUrl) {
        return send(strUrl, GET, null);
    }

    /**
     * @param strUrl
     * @param reqmethod
     * @param reqData
     * @return
     */
    public static byte[] send(String strUrl, String reqmethod, byte[] reqData) {
        try {
            URL url = new URL(strUrl);
            HttpURLConnection httpcon = (HttpURLConnection) url.openConnection();
            httpcon.setDoOutput(true);
            httpcon.setDoInput(true);
            httpcon.setUseCaches(false);
            httpcon.setInstanceFollowRedirects(true);
            httpcon.setConnectTimeout(CONN_TIMEOUT);
            httpcon.setReadTimeout(READ_TIMEOUT);
            httpcon.setRequestMethod(reqmethod);
            httpcon.connect();
            if (reqmethod.equalsIgnoreCase(POST)) {
                OutputStream os = httpcon.getOutputStream();
                os.write(reqData);
                os.flush();
                os.close();
            }
            BufferedReader in = new BufferedReader(new InputStreamReader(httpcon.getInputStream(),"utf-8"));
            String inputLine;
            StringBuilder bankXmlBuffer = new StringBuilder();
            while ((inputLine = in.readLine()) != null) {
                bankXmlBuffer.append(inputLine);
            }
            in.close();
            httpcon.disconnect();
            return bankXmlBuffer.toString().getBytes();
        } catch (Exception ex) {
            log.error(ex.toString(), ex);
            return null;
        }
    }

    /**
     * 从输入流中读取数据
     *
     * @param inStream
     * @return
     * @throws Exception
     */
    public static byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        byte[] data = outStream.toByteArray();// 网页的二进制数据
        outStream.close();
        inStream.close();
        return data;
    }
}

com.myproject.yygh.common.helper.HttpRequestHelper

package com.myproject.yygh.common.helper;

import com.alibaba.fastjson.JSONObject;
import com.myproject.yygh.common.utils.HttpUtil;
import com.myproject.yygh.common.utils.MD5;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

@Slf4j
public class HttpRequestHelper {

    public static void main(String[] args) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("d", "4");
        paramMap.put("b", "2");
        paramMap.put("c", "3");
        paramMap.put("a", "1");
        paramMap.put("timestamp", getTimestamp());
        log.info(getSign(paramMap, "111111111"));
    }

    /**
     *
     * @param paramMap
     * @return
     */
    public static Map<String, Object> switchMap(Map<String, String[]> paramMap) {
        Map<String, Object> resultMap = new HashMap<>();
        for (Map.Entry<String, String[]> param : paramMap.entrySet()) {
            resultMap.put(param.getKey(), param.getValue()[0]);
        }
        return resultMap;
    }

    /**
     * 请求数据获取签名
     * @param paramMap
     * @param signKey
     * @return
     */
    public static String getSign(Map<String, Object> paramMap, String signKey) {
        if(paramMap.containsKey("sign")) {
            paramMap.remove("sign");
        }
        TreeMap<String, Object> sorted = new TreeMap<>(paramMap);
        StringBuilder str = new StringBuilder();
        for (Map.Entry<String, Object> param : sorted.entrySet()) {
            str.append(param.getValue()).append("|");
        }
        str.append(signKey);
        log.info("加密前:" + str.toString());
        String md5Str = MD5.encrypt(str.toString());
        log.info("加密后:" + md5Str);
        return md5Str;
    }

    /**
     * 签名校验
     * @param paramMap
     * @param signKey
     * @return
     */
    public static boolean isSignEquals(Map<String, Object> paramMap, String signKey) {
        String sign = (String)paramMap.get("sign");
        String md5Str = getSign(paramMap, signKey);
        if(!sign.equals(md5Str)) {
            return false;
        }
        return true;
    }

    /**
     * 获取时间戳
     * @return
     */
    public static long getTimestamp() {
        return new Date().getTime();
    }

    /**
     * 封装同步请求
     * @param paramMap
     * @param url
     * @return
     */
    public static JSONObject sendRequest(Map<String, Object> paramMap, String url){
        String result = "";
        try {
            //封装post参数
            StringBuilder postdata = new StringBuilder();
            for (Map.Entry<String, Object> param : paramMap.entrySet()) {
                postdata.append(param.getKey()).append("=")
                        .append(param.getValue()).append("&");
            }
            log.info(String.format("--> 发送请求:post data %1s", postdata));
            byte[] reqData = postdata.toString().getBytes("utf-8");
            byte[] respdata = HttpUtil.doPost(url,reqData);
            result = new String(respdata);
            log.info(String.format("--> 应答结果:result data %1s", result));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return JSONObject.parseObject(result);
    }
}
  1. 在common模块的pom.xml文件中添加fastjson依赖
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
</dependency>

3.1 整合MongoDB

  1. 在service_hosp模块中添加依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
  1. 添加配置
    在application.yml中添加配置
spring:
    data:
        mongodb:
          uri: mongodb://192.168.50.224:27017/yygh_hosp
  1. 医院基础类为model中的com.myproject.yygh.model.hosp.Hospital

  2. 添加Respository
    com.myproject.yygh.hosp.repository.HospitalRepository

package com.myproject.yygh.hosp.repository;

import com.myproject.yygh.model.hosp.Hospital;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface HospitalRepository extends MongoRepository<Hospital,String> {
}
  1. 添加service接口及实现类
    com.myproject.yygh.hosp.service.HospitalService
package com.myproject.yygh.hosp.service;

public interface HospitalService {
}

com.myproject.yygh.hosp.service.impl.HospitalServiceImpl

package com.myproject.yygh.hosp.service.impl;

import com.myproject.yygh.hosp.repository.HospitalRepository;
import com.myproject.yygh.hosp.service.HospitalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class HospitalServiceImpl implements HospitalService {
    @Autowired
    private HospitalRepository hospitalRepository;
}
  1. 添加controller
    com.myproject.yygh.hosp.controller.api.ApiController
package com.myproject.yygh.hosp.controller.api;

import com.myproject.yygh.hosp.service.HospitalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/hosp")
public class ApiController {
    @Autowired
    private HospitalService hospitalService;
}

3.2 上传医院接口

参考《尚医通API接口文档.doc》业务接口4.1上传医院
医院编号是平台分配的,全局唯一,上传医院接口可以多次调用,如果存在相同编号的为更新操作

添加上传医院接口

  1. 添加service接口
    在HospitalService 类添加接口
//上传医院接口
void save(Map<String, Object> paramMap);

说明:参数使用Map,减少对象封装,有利于签名校验,后续会体验到

  1. 在HospitalServiceImpl类添加实现
//上传医院接口
@Override
public void save(Map<String, Object> paramMap) {
    //把参数map集合转换对象 Hospital
    String mapString = JSONObject.toJSONString(paramMap);
    Hospital hospital = JSONObject.parseObject(mapString, Hospital.class);

    //判断是否存在数据
    String hoscode = hospital.getHoscode();
    Hospital hospitalExist = hospitalRepository.getHospitalByHoscode(hoscode);

    //如果存在,进行修改
    if(hospitalExist != null){
        hospital.setId(hospitalExist.getId());
        hospital.setStatus(hospitalExist.getStatus());
        hospital.setCreateTime(hospitalExist.getCreateTime());
        hospital.setUpdateTime(new Date());
        hospital.setIsDeleted(0);
        hospitalRepository.save(hospital);
    }else {//如果不存在,进行添加
        hospital.setStatus(0);
        hospital.setCreateTime(new Date());
        hospital.setUpdateTime(new Date());
        hospital.setIsDeleted(0);
        hospitalRepository.save(hospital);
    }
}
  1. 在HospitalRepository类添加接口
//判断是否存在数据
Hospital getHospitalByHoscode(String hoscode);
  1. 添加controller接口
//上传医院接口
@PostMapping("saveHospital")
public Result saveHosp(HttpServletRequest request){
    //获取传递过来的医院信息
    Map<String, String[]> requestMap = request.getParameterMap();
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(requestMap);
    //调用service的方法
    hospitalService.save(paramMap);
    return Result.ok();
}

测试接口:
启动ServiceHospApplication和ManageApplication
浏览器打开:http://localhost:9998
选择“医院管理” ==> “添加”
输入json数据(前面分享的hospital.json的内容)
保存后可在mongodb可视化软件中查看

添加签名校验功能

  1. 在HospitalSetService中添加接口
//根据传递过来医院编号,查询数据库,查询签名
String getSignKey(Object hoscode);
  1. 在HospitalSetServiceImpl中实现
//根据传递过来医院编号,查询数据库,查询签名
@Override
public String getSignKey(Object hoscode) {
    QueryWrapper<HospitalSet> wrapper = new QueryWrapper<>();
    wrapper.eq("hoscode",hoscode);
    HospitalSet hospitalSet = baseMapper.selectOne(wrapper);

    return hospitalSet.getSignKey();
}
  1. 修改ApiController中的saveHosp方法,添加签名校验功能
@Autowired
private HospitalSetService hospitalSetService;

//上传医院接口
@PostMapping("saveHospital")
public Result saveHosp(HttpServletRequest request){
    //获取传递过来的医院信息
    Map<String, String[]> requestMap = request.getParameterMap();
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(requestMap);

    //签名校验
    isSignEquals(paramMap);

    //传输过程中“+”转换为“ ”,因此我们要转换回来
    String logoData = (String) paramMap.get("logoData");
    logoData = logoData.replaceAll(" ","+");
    paramMap.put("logoData",logoData);

    //调用service的方法
    hospitalService.save(paramMap);
    return Result.ok();
}

public void isSignEquals(Map<String, Object> paramMap){
    //1.获取医院系统传递过来的签名,签名进行MD5加密
    String hospSign = (String)paramMap.get("sign");

    //2.根据传递过来医院编号,查询数据库,查询签名
    String hoscode = (String) paramMap.get("hoscode");
    String signKey = hospitalSetService.getSignKey(hoscode);

    //3.把数据库查询签名进行MD5加密
    String signKeyMd5 = MD5.encrypt(signKey);

    //4.判断签名是否一致
    if(!hospSign.equals(signKeyMd5)){
        throw new YyghException(ResultCodeEnum.SIGN_ERROR);
    }
}
  1. 统一hospital_manage中的签名加密方法
    修改com.myproject.hospital.service.impl.ApiServiceImpl中的saveHospital方法(103行)
paramMap.put("sign", MD5.encrypt(this.getSignKey()));
  1. 测试
    启动ServiceHospApplication和ManageApplication
    浏览器打开:http://localhost:9998
    选择“医院管理” ==> “添加”
    输入json数据(前面分享的hospital.json的内容)
    保存后可在mongodb可视化软件中查看

3.3 查询医院接口

参考《尚医通API接口文档.docx》业务接口4.4查询医院

  1. 添加service接口
    在HospitalService中添加
//根据医院编号进行查询
Hospital getByHoscode(String hoscode);
  1. 在HospitalServiceImpl中实现
//根据医院编号进行查询
@Override
public Hospital getByHoscode(String hoscode) {
    Hospital hospital = hospitalRepository.getHospitalByHoscode(hoscode);
    return hospital;
}
  1. 在ApiController中实现查询医院接口
//查询医院
@PostMapping("hospital/show")
public Result getHospital(HttpServletRequest request){
    //获取传递过来的医院信息
    Map<String, String[]> requestMap = request.getParameterMap();
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(requestMap);
    //签名校验
    isSignEquals(paramMap);

    //获取医院编号
    String hoscode = (String) paramMap.get("hoscode");

    //调用service方法实现根据医院编号查询
    Hospital hospital = hospitalService.getByHoscode(hoscode);
    return Result.ok(hospital);
}
  1. 测试接口
    访问:http://localhost:9998
    点击“医院管理”查看功能是否实现

4.科室接口

参考《尚医通API接口文档.docx》业务接口4.2上传科室

4.1 添加科室基础类

在model中有科室对应的实体类
com.myproject.yygh.model.hosp.Department

添加repository
com.myproject.yygh.hosp.repository.DepartmentRepository

package com.myproject.yygh.hosp.repository;

import com.myproject.yygh.model.hosp.Department;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface DepartmentRepository extends MongoRepository<Department,String> {
}

添加service接口及实现类
com.myproject.yygh.hosp.service.DepartmentService

package com.myproject.yygh.hosp.service;

public interface DepartmentService {
}

com.myproject.yygh.hosp.service.impl.DepartmentServiceImpl

package com.myproject.yygh.hosp.service.impl;

import com.myproject.yygh.hosp.repository.DepartmentRepository;
import com.myproject.yygh.hosp.service.DepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DepartmentServiceImpl implements DepartmentService {
    @Autowired
    private DepartmentRepository departmentRepository;
}

4.2 上传科室接口实现

参考《尚医通API接口文档.doc》业务接口4.2上传科室
医院编号是平台分配的,全局唯一,科室编号为医院自己的编号,相对医院唯一,上传科室接口可以多次调用,如果医院编号与科室编号组合唯一为更新操作

添加service接口

  1. 在DepartmentService中提那家接口
//添加科室信息
void save(Map<String, Object> paramMap);
  1. 在DepartmentServiceImpl类添加实现
//添加科室信息
@Override
public void save(Map<String, Object> paramMap) {
    //paramMap 转换department对象
    String paramMapString = JSONObject.toJSONString(paramMap);
    Department department = JSONObject.parseObject(paramMapString, Department.class);

    //根据医院编号和科室编号查询
    Department departmentExist = departmentRepository.
            getDepartmentByHoscodeAndDepcode(department.getHoscode(),department.getDepcode());

    if(departmentExist != null){
        department.setId(departmentExist.getId());
        department.setCreateTime(departmentExist.getCreateTime());
        department.setUpdateTime(new Date());
        department.setIsDeleted(0);
        departmentRepository.save(department);
    }else{
        department.setCreateTime(new Date());
        department.setUpdateTime(new Date());
        department.setIsDeleted(0);
        departmentRepository.save(department);
    }
}

添加repository接口
在DepartmentRepository添加方法

Department getDepartmentByHoscodeAndDepcode(String hoscode, String depcode);

添加controller接口

@Autowired
private DepartmentService departmentService;

//上传科室接口
@PostMapping("saveDepartment")
public Result saveDepartment(HttpServletRequest request){
    //获取传递过来的医院信息
    Map<String, String[]> requestMap = request.getParameterMap();
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(requestMap);
    //签名校验
    isSignEquals(paramMap);

    //调用service的方法
    departmentService.save(paramMap);
    return Result.ok();
}

测试
启动服务,浏览器访问:http://localhost:9998/
点击“科室列表” ==> “添加”
输入department.json的数据,然后保存
可在可视化界面查看

4.3 查询科室接口

参考《尚医通API接口文档.docx》业务接口4.5查询医院
一个医院有多个科室,因此我们采取分页查询方式

添加service接口
在DepartmentService类添加接口

//查询科室信息
Page<Department> findPageDepartment(int page, int limit, DepartmentQueryVo departmentQueryVo);

在DepartmentServiceImpl类添加实现

//查询科室信息
@Override
public Page<Department> findPageDepartment(int page, int limit, DepartmentQueryVo departmentQueryVo) {
    //创建Pageable对象,设置当前页和每页记录数
    //0是第一页
    Pageable pageable = PageRequest.of(page-1,limit);
    //创建Example对象
    ExampleMatcher matcher = ExampleMatcher.matching()
                    .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
                    .withIgnoreCase(true);

    Department department = new Department();
    BeanUtils.copyProperties(departmentQueryVo,department);
    department.setIsDeleted(0);

    Example<Department> example = Example.of(department,matcher);

    Page<Department> all = departmentRepository.findAll(example,pageable);

    return all;
}

添加controller接口
在ApiController类添加接口

//查询科室接口
@PostMapping("department/list")
public Result findDepartment(HttpServletRequest request){
    //获取传递过来的医院信息
    Map<String, String[]> requestMap = request.getParameterMap();
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(requestMap);
    //签名校验
    isSignEquals(paramMap);

    //医院编号
    String hoscode = (String) paramMap.get("hoscode");

    int page = StringUtils.isEmpty(paramMap.get("page")) ?
            1 : Integer.parseInt((String) paramMap.get("page"));

    int limit = StringUtils.isEmpty(paramMap.get("limit")) ?
            20 : Integer.parseInt((String) paramMap.get("limit"));

    DepartmentQueryVo departmentQueryVo = new DepartmentQueryVo();
    departmentQueryVo.setHoscode(hoscode);
    //调用service方法
    Page<Department> pageModel = departmentService.findPageDepartment(page,limit,departmentQueryVo);

    return Result.ok(pageModel);
}

注:所有page采用import org.springframework.data.domain.Page;

测试接口
启动服务,浏览器访问:http://localhost:9998/
点击“科室列表”查看

4.4 删除科室接口

参考《尚医通API接口文档.docx》业务接口4.7删除科室
根据医院编号与科室编号删除科室

添加service接口
1,在DepartmentService 类添加接口

//删除科室
void remove(String hoscode, String depcode);

2,在DepartmentServiceImpl类添加实现

//删除科室
@Override
public void remove(String hoscode, String depcode) {
    //根据医院编号和科室编号查询
    Department department = departmentRepository.getDepartmentByHoscodeAndDepcode(hoscode, depcode);
    if(department != null){
        //调用方法删除(逻辑删除)
        department.setIsDeleted(1);
        department.setUpdateTime(new Date());
        departmentRepository.save(department);
    }
}

添加controller接口
在ApiController类添加接口

//删除科室接口
@PostMapping("department/remove")
public Result removeDepartment(HttpServletRequest request){
    //获取传递过来的医院信息
    Map<String, String[]> requestMap = request.getParameterMap();
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(requestMap);
    //签名校验
    isSignEquals(paramMap);

    //医院编号 和 科室编号
    String hoscode = (String) paramMap.get("hoscode");
    String depcode = (String) paramMap.get("depcode");

    departmentService.remove(hoscode,depcode);
    return Result.ok();
}

测试接口
启动服务,浏览器访问:http://localhost:9998/
点击“科室列表”,然后删除几个科室查看效果

5.上传排班

参考《尚医通API接口文档.docx》业务接口4.3上传排班

5.1 添加排班基础类

实体类
model模块中的com.myproject.yygh.model.hosp.Schedule

添加repository
com.myproject.yygh.hosp.repository.ScheduleRepository

package com.myproject.yygh.hosp.repository;

import com.myproject.yygh.model.hosp.Schedule;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ScheduleRepository extends MongoRepository<Schedule,String> {
}

添加service接口及实现类

  1. 添加com.myproject.yygh.hosp.service.ScheduleService接口
package com.myproject.yygh.hosp.service;

public interface ScheduleService {
}
  1. 添加com.myproject.yygh.hosp.service.impl.ScheduleServiceImpl接口实现
package com.myproject.yygh.hosp.service.impl;

import com.myproject.yygh.hosp.repository.ScheduleRepository;
import com.myproject.yygh.hosp.service.ScheduleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ScheduleServiceImpl implements ScheduleService {
    @Autowired
    private ScheduleRepository scheduleRepository;
}

5.2 上传排班接口

参考《尚医通API接口文档.doc》业务接口4.3上传排班
医院编号是平台分配的,全局唯一,排班编号为医院自己的编号,相对医院唯一,上传排班接口可以多次调用,如果医院编号与排班编号组合唯一为更新操作

添加service接口
1,在ScheduleService 类添加接口

//上传排班
void save(Map<String, Object> paramMap);

2,在ScheduleServiceImpl类添加实现

//上传排班
@Override
public void save(Map<String, Object> paramMap) {
    //paramMap 转换Schedule对象
    String paramMapString = JSONObject.toJSONString(paramMap);
    Schedule schedule = JSONObject.parseObject(paramMapString, Schedule.class);

    //根据医院编号和排班编号查询
    Schedule scheduleExist = scheduleRepository.
            getScheduleByHoscodeAndHosScheduleId(schedule.getHoscode(),schedule.getHosScheduleId());

    if(scheduleExist != null){
        schedule.setId(scheduleExist.getId());
        schedule.setCreateTime(scheduleExist.getCreateTime());
        schedule.setUpdateTime(new Date());
        schedule.setIsDeleted(0);
        schedule.setStatus(1);
        scheduleRepository.save(schedule);
    }else{
        schedule.setCreateTime(new Date());
        schedule.setUpdateTime(new Date());
        schedule.setIsDeleted(0);
        schedule.setStatus(1);
        scheduleRepository.save(schedule);
    }
}

添加repository接口

//根据医院编号和排班编号查询
Schedule getScheduleByHoscodeAndHosScheduleId(String hoscode, String depcode);

添加controller接口
在ApiController类添加接口

@Autowired
private ScheduleService scheduleService;

//上传排班
@PostMapping("saveSchedule")
public Result saveSchedule(HttpServletRequest request){
    //获取传递过来的医院信息
    Map<String, String[]> requestMap = request.getParameterMap();
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(requestMap);
    //签名校验
    isSignEquals(paramMap);

    scheduleService.save(paramMap);
    return Result.ok();
}

测试接口
启动ServiceHospApplication和ManageApplication
浏览器打开:http://localhost:9998
选择“排班列表” ==> “添加”
输入json数据(前面分享的schedule.json的内容)
保存后可在mongodb可视化软件中查看

5.3 查询排班接口

参考《尚医通API接口文档.docx》业务接口4.6查询医院
一个科室有多个科室,因此我们采取分页查询方式

添加service接口
1,在ScheduleService 类添加接口

//查询排班
Page<Schedule> findPageSchedule(int page, int limit, ScheduleQueryVo scheduleQueryVo);

2,在ScheduleServiceImpl类添加实现

//查询排班
@Override
public Page<Schedule> findPageSchedule(int page, int limit, ScheduleQueryVo scheduleQueryVo) {
    //创建Pageable对象,设置当前页和每页记录数
    //0是第一页
    Pageable pageable = PageRequest.of(page-1,limit);
    //创建Example对象
    ExampleMatcher matcher = ExampleMatcher.matching()
            .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
            .withIgnoreCase(true);

    Schedule schedule = new Schedule();
    BeanUtils.copyProperties(scheduleQueryVo,schedule);
    schedule.setIsDeleted(0);
    schedule.setStatus(1);

    Example<Schedule> example = Example.of(schedule,matcher);

    Page<Schedule> all = scheduleRepository.findAll(example,pageable);

    return all;
}

添加controller接口

//查询排班
@PostMapping("schedule/list")
public Result findSchedule(HttpServletRequest request){
    //获取传递过来的医院信息
    Map<String, String[]> requestMap = request.getParameterMap();
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(requestMap);
    //签名校验
    isSignEquals(paramMap);

    //医院编号 和 科室编号
    String hoscode = (String) paramMap.get("hoscode");
    String depcode = (String) paramMap.get("depcode");

    int page = StringUtils.isEmpty(paramMap.get("page")) ?
            1 : Integer.parseInt((String) paramMap.get("page"));

    int limit = StringUtils.isEmpty(paramMap.get("limit")) ?
            20 : Integer.parseInt((String) paramMap.get("limit"));

    ScheduleQueryVo scheduleQueryVo = new ScheduleQueryVo();
    scheduleQueryVo.setHoscode(hoscode);
    scheduleQueryVo.setDepcode(depcode);

    //调用service方法
    Page<Schedule> pageModel = scheduleService.findPageSchedule(page,limit,scheduleQueryVo);

    return Result.ok(pageModel);
}

测试接口
启动ServiceHospApplication和ManageApplication
浏览器打开:http://localhost:9998
选择“排班列表” 查看效果

5.4 删除排班功能

参考《尚医通API接口文档.docx》业务接口4.8删除科室
根据医院编号与排班编号删除科室

添加service接口
1,在ScheduleService 类添加接口

//删除排班
void remove(String hoscode, String hosScheduleId);

2,在ScheduleServiceImpl类添加实现

//删除排班
@Override
public void remove(String hoscode, String hosScheduleId) {
    //根据医院编号和排班编号查询信息
    Schedule schedule = scheduleRepository.getScheduleByHoscodeAndHosScheduleId(hoscode,hosScheduleId);
    if(schedule != null){
        //逻辑删除
        schedule.setIsDeleted(1);
        scheduleRepository.save(schedule);
    }
}

添加controller接口
在ApiController类添加接口

//删除排班
@PostMapping("schedule/remove")
public Result remove(HttpServletRequest request){
    //获取传递过来的医院信息
    Map<String, String[]> requestMap = request.getParameterMap();
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(requestMap);
    //签名校验
    isSignEquals(paramMap);

    //获取医院编号和排班编号
    String hoscode = (String) paramMap.get("hoscode");
    String hosScheduleId = (String) paramMap.get("hosScheduleId");

    scheduleService.remove(hoscode,hosScheduleId);
    return Result.ok();
}

测试删除接口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值