首页 > 编程语言 >尚医通-day06【医院模拟系统接口详细步骤】(内附源码)

尚医通-day06【医院模拟系统接口详细步骤】(内附源码)

时间:2023-06-12 19:33:57浏览次数:58  
标签:hoscode String 尚医通 day06 接口 医院 源码 paramMap public

第01章-医院系统

1、业务功能描述

资料:资料>医院模拟系统>尚医通API接口文档.docx

1.1、平台方

参考《尚医通API接口文档.docx》进行业务接口的开发,接收医院方的接口调用,将医院信息、科室信息、排班信息等数据存入MongoDB。

1.2、医院方

每个医院有自己的业务平台,需参考《尚医通API接口文档.docx》进行接口调用与数据上传,将本院的医院信息、科室信息、排班信息等数据上传到统一挂号平台。

2、部署医院端程序

2.1、创建yygh_manage数据库

资料:资料>医院模拟系统>yygh_manage.sql

2.2、运行医院程序

资料:资料>医院模拟系统>hospital-manage.zip

用idea打开医院端程序,修改数据库配置和maven配置 ,运行启动类

访问http://localhost:9998

2. 3、添加医院设置信息

平台端数据库guigu_syt_hosp中的hospital_set表中为每个需要接入平台的医院配置医院设置信息,例如“北京协和医院”,并生成医院编号和signKey

image-20230214130252914

医院端数据库guigu_yygh_manage中的hospital_set表配置医院设置信息,确保医院编号和signKey和平台端一致

image-20230214130217906

医院编号:是平台为医院颁发的,每个医院唯一。

signKey:是平台为医院颁发的,用于生成签名,确保数据传输过程的不可篡改。

第02章-接口安全

1、数字签名

1.1、对称加密

image-20230214233043970

1.2、非对称加密

image-20230214220611797

1.3、摘要算法

实现完整性的手段主要是摘要算法(Digest Algorithm),也就是我们常说的哈希函数。假设一个任意长的数据 z,经过哈希运算后会得到固定长度的数据 h,h 就是z的哈希结果又称作“数据指纹“ 或 “摘要”。MD5就是一个摘要算法摘要算法必须具有下面的 4 种特性:

不可逆:只有算法,没有秘钥,只能加密,不能解密
难题友好性:想要破解,只能暴力枚举
发散性:只要对原文进行一点点改动,摘要就会发生剧烈变化
抗碰撞性:原文不同,计算后的摘要也要不同

常见摘要算法:MD5、SHA1、SHA2(SHA224、SHA256、SHA384)

1.4、数字签名的原理

信息完整性

  • Bob有两把钥匙,一把公钥(public key),一把私钥(private key)
  • Bob把公钥送给他的朋友们,每人一把。Bob的私钥自己保留。

image-20230214220701239

Bob决定给Pat写一封信,要保证Pat收到信后,能够确认信的内容没有被篡改过,也就是需要保证信息的完整性。我们可以利用摘要运算,具体的流程是这样的:

  • 第一步:Bob写完信后,先用摘要算法(MD5、SHA),生成信件原文的摘要(Digest)
  • 第二步:Bob将摘要附在信件的原文下面,一起发给Pat

Pat收信后,也是两个步骤:

  • 第一步:Pat使用和Bob一样的摘要算法加密信件的原文得到信件的摘要。
  • 第二步:Pat将加密后的摘要,和Bob在原文中附加的摘要做对比,如果一致,说明信件没有篡改。

image-20230214215018998

问题:这种方式看似解决了数据完整性的问题,但是有一个致命的漏洞,就是,如果信件原文不加密,并且被黑客截获,黑客直接修改了原文,并且根据原文直接生成了新的摘要,然后附加在原文的下面,伪装成Bob将信件发给Pat,那么Pat接收后,是完全察觉不出来信件其实已经被篡改了。所以说摘要算法不具有机密性,如果明文传输,那么黑客可以修改消息后把摘要也一起改了,还是鉴别不出信息的完整性。

解决方案:我们可以使用非对称加密中的私钥,将摘要进行加密处理。

具体的流程是:

  • 第一步:Bob写完信后,先用摘要算法(MD5、SHA),生成信件的摘要(Digest)
  • 第二步:Bob使用自己的私钥,将摘要加密。加密后的结果,我们称之为“数字签名”Signature
  • 第三步:Bob将数字签名附在信的原文下面,一起发给Pat

Pat收信后,也是三个步骤:

第一步:Pat取下数字签名,用Bob的公钥解密,得到信件的摘要。

第二步:Pat使用和Bob一样的摘要算法加密信件的原文,得到信件的摘要。

第三步:将前面两部得到的摘要进行比对,如果一致,信件是就是Bob发的,并且没有经过篡改

这个过程叫做“验签”,也就是验证签名通过Bob的签名流程和Pat的验签流程,我们发现即使信件被黑客截获,即使黑客能够篡改信件原文,即使黑客能够通过摘要算法生成新的摘要,但是因为他没有Bob的私钥,因此无法对摘要进行加密,无法生成只有Bob才能生成的签名,所以信件也就无法被篡改了。微信支付中的签名和验签的过程就是这个原理。经过以上步骤,我们就可以取出信件原文了。

image-20230214215043784

  • 上面,我们讲解的数字签名的生成,这里使用了非对称加密+摘要算法的方式,在对安全性要求较高的系统中(如支付系统),会采用这种接口安全策略。
  • 尚医通项目中医院和平台间接口的调用对安全性的要求没有那么高,因此没有使用非对称加密的方式,使用了对称加密+摘要算法的方式。

2、获取签名密钥

2.1、引入依赖

service-util中引入依赖

<!--fastjson-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
</dependency>

2.2、工具类

将工具类复制到service-util的utils包中

资料:资料>医院模拟系统>工具类

2.3、签名的过程

尚医通的签名算法:参考《尚医通API接口文档.docx》 3.1传参说明

2.4、签名密钥的获取

接口:HospitalSetService

/**
     * 根据医院编码获取医院签名密钥
     * @param hoscode
     * @return
     */
String getSignKey(String hoscode);

/**
     * 根据hoscode获取医院设置
     * @param hoscode
     * @return
     */
HospitalSet getByHoscode(String hoscode);

实现:HospitalSetServiceImpl

@Override
public String getSignKey(String hoscode) {
    HospitalSet hospitalSet = this.getByHoscode(hoscode);
    if(hospitalSet == null) {
        throw new GuiguException(ResultCodeEnum.HOSPITAL_OPEN);
    }
    if(hospitalSet.getStatus().intValue() == 0) {
        throw new GuiguException(ResultCodeEnum.HOSPITAL_LOCK);
    }
    return hospitalSet.getSignKey();
}

@Override
public HospitalSet getByHoscode(String hoscode) {
    return baseMapper.selectOne(
        new LambdaQueryWrapper<HospitalSet>().eq(HospitalSet::getHoscode, hoscode)
    );
}

第03章-接口开发

1、上传医院信息接口

1.1、创建Repository

service-hosp中添加接口HospitalRepository

package com.atguigu.syt.hosp.repository;
public interface HospitalRepository extends MongoRepository<Hospital,ObjectId> {
    /**
     * 根据医院编号查询医院
     * @param hoscode
     * @return
     */
	Hospital findByHoscode(String hoscode);
}

1.2、创建Service

接口:HospitalService

package com.atguigu.syt.hosp.service;
public interface HospitalService {
     /**
     * 保存医院信息
     * @param paramMap
     */ 
    void save(Map<String, Object> paramMap);
}

实现:HospitalServiceImpl

package com.atguigu.syt.hosp.service.impl;

@Service
public class HospitalServiceImpl implements HospitalService {

    @Resource
    private HospitalRepository hospitalRepository;

    /**
     * 添加医院信息
     * @param paramMap
     */
    @Override
    public void save(Map<String, Object> paramMap) {
        //把paramMap变成对象
        Hospital hospital = JSONObject.parseObject(JSONObject.toJSONString(paramMap), Hospital.class);
        //根据医院编号查询医院信息是否已经添加
        Hospital existHospital = hospitalRepository.findByHoscode(hospital.getHoscode());
        //如果已经添加过,则修改
        if(existHospital != null) {
            //设置id
            hospital.setId(existHospital.getId());
            hospital.setStatus(existHospital.getStatus());
            hospitalRepository.save(hospital);
        } else {
            //如果没有添加,则添加
            //0:未上线 1:已上线
            hospital.setStatus(1);
            hospitalRepository.save(hospital);
        }
    }
}

1.3、创建Controller

在controller包中创建api包,创建ApiController类

package com.atguigu.syt.hosp.controller.api;

@Api(tags = "医院管理API接口")
@RestController
@RequestMapping("/api/hosp")
public class ApiController {

    @Resource
    private HospitalService hospitalService;

    @Resource
    private HospitalSetService hospitalSetService;

    @ApiOperation(value = "上传医院基本信息")
    @PostMapping("/saveHospital")
    public Result saveHospital(HttpServletRequest request) {
        Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());

        //签名验证
        String hoscode = (String)paramMap.get("hoscode");
        String signKey = hospitalSetService.getSignKey(hoscode);
        HttpRequestHelper.checkSign(paramMap, signKey);

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

1.4、测试

运行医院端程序,测试医院信息的添加
img

医院端相关代码:hospital-manage:controller.ApiCOntroller.saveHospital

注意:在spring-security的AuthorizationWebSecurityConfig类中,我们配置了授权校验排除了api路径

/**
     * 配置哪些请求不拦截
     * 排除swagger相关请求
     * @param web
     * @throws Exception
     */
@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/api/**", "/favicon.ico","/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**", "/doc.html");
}

2、查询医院信息接口

2.1、ApiController

@ApiOperation(value = "获取医院信息")
@PostMapping("/hospital/show")
public Result hospital(HttpServletRequest request) {
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());

    //签名验证
    String hoscode = (String)paramMap.get("hoscode");
    String signKey = hospitalSetService.getSignKey(hoscode);
    HttpRequestHelper.checkSign(paramMap, signKey);

    Hospital hospital = hospitalService.getByHoscode(hoscode);
    return Result.ok(hospital);
}

2.2、Service

接口:HospitalService

/**
     * 根据医院编码获取医院信息
     * @param hoscode
     * @return
     */
Hospital getByHoscode(String hoscode);

实现:HospitalServiceImpl

@Override
public Hospital getByHoscode(String hoscode) {
    return hospitalRepository.findByHoscode(hoscode);
}

2.3、测试

测试查看医院信息:

image-20230215072650557

医院端相关代码:hospital-manage:controller.ApiCOntroller.getHospital

3、上传科室接口

3.1、创建Repository

service-hosp中添加接口DepartmentRepository

package com.atguigu.syt.hosp.repository;

public interface DepartmentRepository extends MongoRepository<Department,ObjectId> {
    //根据医院编号和科室编号查询科室
	Department findByHoscodeAndDepcode(String hoscode, String depcode);
}

3.2、创建Service

接口:DepartmentService

package com.atguigu.syt.hosp.service;

public interface DepartmentService {
     /**
     * 保存科室信息
     * @param paramMap
     */ 
    void save(Map<String, Object> paramMap);
}

实现:DepartmentServiceImpl

package com.atguigu.syt.hosp.service.impl;

@Service
public class DepartmentServiceImpl implements DepartmentService {

    @Resource
    private DepartmentRepository departmentRepository;

    @Override
    public void save(Map<String, Object> paramMap) {

        // 把paramMap变成对象
        Department department = JSONObject.parseObject(JSONObject.toJSONString(paramMap), Department.class);

        //查询科室是否存在  医院编号 + 科室编号
        Department existsDepartment = departmentRepository.findByHoscodeAndDepcode(
                department.getHoscode(),
                department.getDepcode());

        //判断
        if(existsDepartment != null) { //修改
            department.setId(existsDepartment.getId());
            departmentRepository.save(department);
        } else {
            departmentRepository.save(department);
        }
    }
}

3.3、添加Controller方法

在ApiController中添加方法

@Resource
private DepartmentService departmentService;

@ApiOperation(value = "上传科室")
@PostMapping("/saveDepartment")
public Result saveDepartment(HttpServletRequest request) {
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());

    //签名验证
    String hoscode = (String)paramMap.get("hoscode");
    String signKey = hospitalSetService.getSignKey(hoscode);
    HttpRequestHelper.checkSign(paramMap, signKey);

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

3.4、测试

运行医院端程序,测试部门信息的添加

image-20230215124253926

4、查询科室接口

4.1、添加Service方法

接口:DepartmentService

/**
     * 分页查询
     * @param page 当前页码
     * @param limit 每页记录数
     * @param hoscode 查询条件
     * @return
     */
Page<Department> selectPage(int page, int limit, String hoscode);

实现:DepartmentServiceImpl

@Override
public Page<Department> selectPage(int page, int limit, String hoscode) {
    //设置排序规则
    Sort sort = Sort.by(Sort.Direction.ASC, "depcode");
    //设置分页参数
    Pageable pageable = PageRequest.of(page-1, limit, sort);
    //创建查询对象
    Department department = new Department();
    department.setHoscode(hoscode);
    Example<Department> example = Example.of(department);
    //执行查询
    Page<Department> pages = departmentRepository.findAll(example, pageable);
    return pages;
}

4.2、添加Controller方法

在ApiController中添加方法

@ApiOperation(value = "获取分页列表")
@PostMapping("/department/list")
public Result department(HttpServletRequest request) {
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());
    
    //签名验证
    String hoscode = (String)paramMap.get("hoscode");
    String signKey = hospitalSetService.getSignKey(hoscode);
    HttpRequestHelper.checkSign(paramMap, signKey);
    
    int page = Integer.parseInt((String)paramMap.get("page"));
    int limit = Integer.parseInt((String)paramMap.get("limit"));
    Page<Department> pageModel = departmentService.selectPage(page, limit, hoscode);
    return Result.ok(pageModel);
}

5、删除科室接口

5.1、添加Service方法

接口:DepartmentService

/**
     * 根据医院编码和科室编码删除科室
     * @param hoscode
     * @param depcode
     */
void remove(String hoscode, String depcode);

实现:DepartmentServiceImpl

@Override
public void remove(String hoscode, String depcode) {
    //根据医院编号、科室编号查询
    Department department = departmentRepository.findByHoscodeAndDepcode(hoscode, depcode);
    //判断查询出来数据,根据科室id删除
    if(department != null) {
        departmentRepository.deleteById(department.getId());
    }
}

5.2、添加Controller方法

@ApiOperation(value = "删除科室")
@PostMapping("/department/remove")
public Result removeDepartment(HttpServletRequest request) {
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());

    //签名验证
    String hoscode = (String)paramMap.get("hoscode");
    String signKey = hospitalSetService.getSignKey(hoscode);
    HttpRequestHelper.checkSign(paramMap, signKey);

    String depcode = (String)paramMap.get("depcode");
    departmentService.remove(hoscode, depcode);
    return Result.ok();
}

6、上传排班接口

6.1、创建Repository

package com.atguigu.syt.hosp.repository;

public interface ScheduleRepository extends MongoRepository<Schedule,ObjectId> {
    /**
     * 根据医院编码和医院端排版id查询排班记录
     * @param hoscode
     * @param hosScheduleId
     * @return
     */
    Schedule findByHoscodeAndHosScheduleId(String hoscode, String hosScheduleId);
}

6.2、创建Service

接口:ScheduleService

package com.atguigu.syt.hosp.service;
public interface ScheduleService {

    /**
     * 保存排班信息
     * @param paramMap
     */
    void save(Map<String, Object> paramMap);
}

实现:ScheduleServiceImpl

package com.atguigu.syt.hosp.service.impl;

@Service
public class ScheduleServiceImpl implements ScheduleService {

    @Resource
    private ScheduleRepository scheduleRepository;

    @Override
    public void save(Map<String, Object> paramMap) {

        //数据转换
        Schedule schedule = JSONObject.parseObject(JSONObject.toJSONString(paramMap), Schedule.class);
        //查询mongodb中数据是否存在
        Schedule existSchedule = scheduleRepository.findByHoscodeAndHosScheduleId(
                schedule.getHoscode(),
                schedule.getHosScheduleId()
        );

        //如果不存在
        if(existSchedule != null){//更新
            schedule.setId(existSchedule.getId());
            scheduleRepository.save(schedule);
        }else{//新增
            scheduleRepository.save(schedule);
        }
    }
}

6.3、添加Controller

ApiController

@Resource
private ScheduleService scheduleService;

@ApiOperation(value = "上传排班")
@PostMapping("/saveSchedule")
public Result saveSchedule(HttpServletRequest request) {
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());

    //签名验证
    String hoscode = (String)paramMap.get("hoscode");
    String signKey = hospitalSetService.getSignKey(hoscode);
    HttpRequestHelper.checkSign(paramMap, signKey);

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

7、查询排班接口

7.1、添加Service方法

接口:ScheduleService

/**
     * 分页查询
     * @param page 当前页码
     * @param limit 每页记录数
     * @param hoscode 查询条件
     * @return
     */
Page<Schedule> selectPage(int page, int limit, String hoscode);

实现:ScheduleServiceImpl

@Override
public Page<Schedule> selectPage(int page, int limit, String hoscode) {
    //设置排序规则
    Sort sort = Sort.by(Sort.Direction.ASC, "workDate");
    //设置分页参数
    Pageable pageable = PageRequest.of(page-1, limit, sort);
    //创建查询对象
    Schedule schedule = new Schedule();
    schedule.setHoscode(hoscode);
    Example<Schedule> example = Example.of(schedule);
    Page<Schedule> pages = scheduleRepository.findAll(example, pageable);
    return pages;
}

7.2、添加Controller方法

@ApiOperation(value = "获取排班分页列表")
@PostMapping("/schedule/list")
public Result schedule(HttpServletRequest request) {
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());

    //签名验证
    String hoscode = (String)paramMap.get("hoscode");
    String signKey = hospitalSetService.getSignKey(hoscode);
    HttpRequestHelper.checkSign(paramMap, signKey);

    int page = Integer.parseInt((String)paramMap.get("page"));
    int limit = Integer.parseInt((String)paramMap.get("limit"));
    Page<Schedule> pageModel = scheduleService.selectPage(page, limit, hoscode);
    return Result.ok(pageModel);
}

8、删除排班接口

8.1、添加Service

接口:ScheduleService

/**
     * 根据医院编码和排班id删除排班
     * @param hoscode
     * @param hosScheduleId
     */
void remove(String hoscode, String hosScheduleId);

实现:ScheduleServiceImpl

@Override
public void remove(String hoscode, String hosScheduleId) {
    Schedule schedule = scheduleRepository.findByHoscodeAndHosScheduleId(hoscode, hosScheduleId);
    if(null != schedule) {
        scheduleRepository.deleteById(schedule.getId());
    }
}

8.2、添加Controller接口

@ApiOperation(value = "删除排班")
@PostMapping("/schedule/remove")
public Result removeSchedule(HttpServletRequest request) {
    Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());

    //签名验证
    String hoscode = (String)paramMap.get("hoscode");
    String signKey = hospitalSetService.getSignKey(hoscode);
    HttpRequestHelper.checkSign(paramMap, signKey);

    String hosScheduleId = (String)paramMap.get("hosScheduleId");
    scheduleService.remove(hoscode, hosScheduleId);
    return Result.ok();
}

源码:https://gitee.com/dengyaojava/guigu-syt-parent

标签:hoscode,String,尚医通,day06,接口,医院,源码,paramMap,public
From: https://www.cnblogs.com/deyo/p/17475901.html

相关文章

  • 尚医通-day08【排班管理详细步骤】(内附源码)
    页面预览医院详情排班管理第01章-医院详情1、后端1.1、ControllerAdminHospitalController@ApiOperation(value="获取医院详情")@ApiImplicitParam(name="hoscode",value="医院编码",required=true)@GetMapping("/show/{hoscode}")publicResult......
  • 尚医通day01-【项目环境搭建和医院设置详细步骤】(内附源码)
    第01章-项目介绍1、课程介绍项目名称:尚医通预约挂号统一平台项目原型:https://www.114yygh.com北京市预约挂号统一平台项目技术栈:前后端分离后端技术:SpringBoot+SpringCloud+MyBatisPlus+MySQL+MongoDB+Redis+RabbitMQ+Docker+EasyExcel+API远程接口调......
  • 尚医通-day02【医院设置前端详细步骤】(内附源码)
    页面预览列表页面新增页面编辑页面第01章-项目中的路由1、引入路由1.1、路由模块中定义路由src/router/index.js关键代码importVuefrom'vue'//引入vue模块importRouterfrom'vue-router'//引入路由模块Vue.use(Router)//挂载路由功能到vue框架中exportc......
  • 尚医通day09-【用户平台搭建详细步骤】(内附源码)
    页面预览首页医院详情第01章-服务器端渲染和客户端渲染1、搜索引擎优化1.1、什么是搜索引擎优化SEO是网站为了获得更多的流量,对网站的结构及内容进行调整和优化,以便搜索引擎(百度,google等)更好抓取到网站的内容,提高自已的网站排名。1.2、搜索引擎工作流程1.3、简单的S......
  • 社交app源码技术屏幕的两大实用功能
    在这个大部分人都是独生子的时代,很多人都会因为没有朋友或是在外地、亲人不在身边而孤独,这时候,很多人就会去选择去社交app软件,这也促使了社交app源码搭建平台的火爆,但是要想搭建出一个令用户满意的社交app平台,就要去了解用户需要什么样的社交app源码技术功能,今天我要讲的也是用户需......
  • 视频直播网站源码,vue tabs标签页 点击才加载
    视频直播网站源码,vuetabs标签页点击才加载tabs标签页,默认加载显示第1个tab; <el-tabsv-model="tTab"type="card"style="height:100%"@tab-click="tTabClick">  <el-tab-panelabel="Jupyter"name="Jupyter">   ......
  • std::string源码探秘和性能分析
    std::string源码探秘和性能分析2016年05月05日22:15:15std::string源码探秘和性能分析本文主要讲c++标准库的string的内部实现,以及对象拷贝的性能分析。文中采用的源码版本为gcc-4.9,测试环境为centos7,x86_64,涉及到指针等数据类型的大小也假定是在64环境位下。stl源码可以在......
  • dubbo源码深度分析:62个文档+中文注释+流程图+思维导图
    你好,我是田哥为满足群里大部分同学的需求,国庆期间,我重新对Dubbo源码进行梳理,一共7个内容:1、Dubbo核心知识总结2、Dubbo源码分析指南3、Dubbo服务发布流程4、Dubbo服务调用流程5、Dubbo中文版注释6、共62节Dubbo文档7、看Dubbo源码必备的知识点咱们话不多说,直接看内容。Dubbo核心知......
  • springboot+vue留守儿童爱心网站,附源码+数据库+论文+PPT,远程包安装运行
    1、项目介绍留守儿童爱心网站采用了B/S结构,JAVA作为开发语言,数据库采用了B/S结构,Mysql数据库进行开发。该系统包括前台操作,后台由管理员和用户两个部分,一方面,为用户提供首页、宣传新闻、志愿活动、爱心捐赠、个人中心、后台管理等功能;另一方面,为管理员提供首页、个人中心、用户管......
  • 家居购买管理系统(含源码)
    家居购买管理系统源码地址:https://pan.baidu.com/s/1UWQTntNOIiJ5xlaby6R60Q?pwd=cwq6提取码:cwq6开发工具:IDEA2021负责模块:主要负责管理员的订单管理、商品管理和用户的订单管理、购物车管理、首页、登录功能、后端的接口设计和实现。技术选型:java+jsp+MySQL+servlet1.模拟......