后端-数据接口-上传医院信息环境搭建及实现

参考《尚医通API接口文档.docx》业务接口4.1上传医院
参考《医院接口模拟系统.docx》进行接口测试与数据上传

1、添加公共基础类

1.1、添加基础工具类

在这里插入图片描述
HttpUtil:

package com.study.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;
	}
}

HttpRequestHelper:

package com.study.yygh.common.helper;

import com.alibaba.fastjson.JSONObject;
import com.study.yygh.common.utils.HttpUtil;
import com.study.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);
    }
}

2、集成mongoDB

2.1、添加依赖

service-hosp模块pom.xml添加依赖

<!--springboot整合mongodb-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

2.2、添加配置

在application.properties文件添加配置

# mongoDB
spring.data.mongodb.uri=mongodb://127.0.0.1:27017/yygh_hosp

说明:改为自己安装mongodb的ip地址

3、 上传医院信息基础环境搭建

3.1、创建实体类

在这里插入图片描述BaseMongoEntity:

package com.study.yygh.model.base;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.data.annotation.Id;
import lombok.Data;
import org.springframework.data.annotation.Transient;

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

@Data
public class BaseMongoEntity implements Serializable {

    @ApiModelProperty(value = "id")
    @Id
    private String id;

    @ApiModelProperty(value = "创建时间")
    private Date createTime;

    @ApiModelProperty(value = "更新时间")
    private Date updateTime;

    @ApiModelProperty(value = "逻辑删除(1:已删除,0:未删除)")
    private Integer isDeleted;

    @ApiModelProperty(value = "其他参数")
    @Transient //被该注解标注的,将不会被录入到数据库中。只作为普通的javaBean属性
    private Map<String,Object> param = new HashMap<>();
}

BookingRule:

package com.study.yygh.model.hosp;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.study.yygh.model.base.BaseEntity;
import com.study.yygh.model.base.BaseMongoEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * <p>
 * RegisterRule
 * </p>
 *
 * @author qy
 */
@Data
@ApiModel(description = "预约规则")
@Document("BookingRule")
public class BookingRule {
	
	@ApiModelProperty(value = "预约周期")
	private Integer cycle;

	@ApiModelProperty(value = "放号时间")
	private String releaseTime;

	@ApiModelProperty(value = "停挂时间")
	private String stopTime;

	@ApiModelProperty(value = "退号截止天数(如:就诊前一天为-1,当天为0)")
	private Integer quitDay;

	@ApiModelProperty(value = "退号时间")
	private String quitTime;

	@ApiModelProperty(value = "预约规则")
	private List<String> rule;

	/**
	 *
	 * @param rule
	 */
	public void setRule(String rule) {
		if(!StringUtils.isEmpty(rule)) {
			this.rule = JSONArray.parseArray(rule, String.class);
		}
	}

}

Hospital:

package com.study.yygh.model.hosp;

import com.alibaba.fastjson.JSONObject;
import com.study.yygh.model.base.BaseEntity;
import com.study.yygh.model.base.BaseMongoEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

/**
 * <p>
 * Hospital
 * </p>
 *
 * @author qy
 */
@Data
@ApiModel(description = "Hospital")
@Document("Hospital")
public class Hospital extends BaseMongoEntity {
	
	private static final long serialVersionUID = 1L;
	
	@ApiModelProperty(value = "医院编号")
	@Indexed(unique = true) //唯一索引
	private String hoscode;

	@ApiModelProperty(value = "医院名称")
	@Indexed //普通索引
	private String hosname;

	@ApiModelProperty(value = "医院类型")
	private String hostype;

	@ApiModelProperty(value = "省code")
	private String provinceCode;

	@ApiModelProperty(value = "市code")
	private String cityCode;

	@ApiModelProperty(value = "区code")
	private String districtCode;

	@ApiModelProperty(value = "详情地址")
	private String address;

	@ApiModelProperty(value = "医院logo")
	private String logoData;

	@ApiModelProperty(value = "医院简介")
	private String intro;

	@ApiModelProperty(value = "坐车路线")
	private String route;

	@ApiModelProperty(value = "状态 0:未上线 1:已上线")
	private Integer status;

	//预约规则
	@ApiModelProperty(value = "预约规则")
	private BookingRule bookingRule;

	public void setBookingRule(String bookingRule) {
		this.bookingRule = JSONObject.parseObject(bookingRule, BookingRule.class);
	}

}

3.2、创建Repository,用于使用mongoDB

在这里插入图片描述

@Repository
public interface HospitalRepository extends MongoRepository<Hospital,String> {
}

3.3、创建service接口及实现类

service接口
在这里插入图片描述

public interface HospitalService {
}

接口实现类:
在这里插入图片描述

@Service
public class HospitalServiceImpl implements HospitalService {

    @Autowired
    private HospitalRepository hospitalRepository;
}

3.4、创建控制层

在这里插入图片描述

@RestController
@RequestMapping("/api/hosp")
public class ApiController {

    @Autowired
    private HospitalService hospitalService;
}

4、上传医院信息接口实现

4.1、控制层

编写控制层方法,实现医院信息上传。
在这里插入图片描述

@RestController
@RequestMapping("/api/hosp")
public class ApiController {

    @Autowired
    private HospitalService hospitalService;

    //上传医院信息
    @PostMapping("/saveHospital")
    public Result saveHospital(HttpServletRequest request){
        //获取传递过来的医院信息
        Map<String, String[]> requestMap = request.getParameterMap();
        //将Map<String, String[]> 形式转换成Map<String, Object>方便后续使用
        Map<String, Object>  paramMap = HttpRequestHelper.switchMap(requestMap);
        //调用service方法
        hospitalService.save(paramMap);
        return Result.ok();
    }
}

4.2、业务层

接口:
在这里插入图片描述实现类:
在这里插入图片描述

@Service
public class HospitalServiceImpl implements HospitalService {

    @Autowired
    private HospitalRepository hospitalRepository;

    //上传医院信息
    @Override
    public void save(Map<String, Object> paramMap) {
        //将map集合转换成字符串
        String mapString = JSONObject.toJSONString(paramMap);
        //将字符串转成Hospital对象
        Hospital hospital = JSONObject.parseObject(mapString, Hospital.class);

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

        //如果存在数据,进行更新
        if(hospitalExist != null){
            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);
        }
        
    }
}

4.3、在HospitalRepository编写方法进行数据操作

我们只要按照spring data规范编写方法,就可以不用写相关sql。
在这里插入图片描述

Spring Data提供了对mongodb数据访问的支持,我们只需要继承MongoRepository类,按照Spring Data规范就可以了。
SpringData 方法定义规范
在这里插入图片描述
在这里插入图片描述
注意:
1、、不是随便声明的,而需要符合一定的规范
2、 查询方法以find | read | get开头
3、 涉及条件查询时,条件的属性用条件关键字连接
4、 要注意的是:条件属性首字母需要大写
5、 支持属性的级联查询,但若当前类有符合条件的属性则优先使用,而不使用级联属性,若需要使用级联属性,则属性之间使用_强制进行连接

5、参数签名校验

5.1、在上传医院方法中添加签名校验

我们在医院设置的时候,为每个医院生成了医院编码与签名key,因此在验证签名时要根据医院编码去动态获取签名key,然后再做签名校验。

在医院信息上传接口中做医院签名信息的校验:
在这里插入图片描述

//上传医院信息
@PostMapping("/saveHospital")
public Result saveHospital(HttpServletRequest request){
    //获取传递过来的医院信息
    Map<String, String[]> requestMap = request.getParameterMap();
    //将Map<String, String[]> 形式转换成Map<String, Object>方便后续使用
    Map<String, Object>  paramMap = HttpRequestHelper.switchMap(requestMap);

    //1、获取医院传递过来的签名,签名进行MD5加密
    String hospSign = (String)paramMap.get("sign");

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

    //3、把数据库拆线呢的签名进行加密
    String signKeyMD5 = MD5.encrypt(signKey);

    //3、判断签名是否一致
    if(!hospSign.equals(signKeyMD5)){
        throw new YyghException(ResultCodeEnum.SIGN_ERROR);
    }

    //传输过程中 “+” 转换为了“ ”,因此我们要转换回来
    String logoData = (String)paramMap.get("logoData");
    logoData = logoData.replaceAll(" ","+");
    paramMap.put("logoData",logoData);
    
    //调用service方法
    hospitalService.save(paramMap);
    return Result.ok();
}

6、 图片base64编码

6.1、 图片base64说明

图片的base64编码就是可以将一张图片数据编码成一串字符串,使用该字符串代替图像地址url
在前端页面中常见的base64图片的引入方式:
<img src="data:image/png;base64,iVBORw0…”/>

  1. 优点
    (1)base64格式的图片是文本格式,占用内存小,转换后的大小比例大概为1/3,降低了资源服务器的消耗;
    (2)网页中使用base64格式的图片时,不用再请求服务器调用图片资源,减少了服务器访问次数。

  2. 缺点
    (1)base64格式的文本内容较多,存储在数据库中增大了数据库服务器的压力;
    (2)网页加载图片虽然不用访问服务器了,但因为base64格式的内容太多,所以加载网页的速度会降低,可能会影响用户的体验。

说明:医院logo图片小,因此上传医院logo是可以使用base64格式保存

6.2、 图片base64工具类

在common-util模块添加工具类
添加com.atguigu.yygh.common.util.ImageBase64Util类
package com.atguigu.yygh.common.util;

import org.apache.commons.codec.binary.Base64;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class ImageBase64Util {

public static void main(String[] args) {
String imageFile= “D:\yygh_work\xh.png”;// 待处理的图片
System.out.println(getImageString(imageFile));
}

public static String getImageString(String imageFile){
InputStream is = null;
try {
byte[] data = null;
is = new FileInputStream(new File(imageFile));
data = new byte[is.available()];
is.read(data);
return new String(Base64.encodeBase64(data));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != is) {
try {
is.close();
is = null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
return “”;
}
}

6.3、 上传医院接口修正

图片转换为base64字符串时,该字符串中包含大量的加号“+”,服务器在解析数据时会把加号当成连接符,转换为空格,因此我们要做一下特殊处理
修改ApiController类上传接口
在这里插入图片描述

@RestController
@RequestMapping("/api/hosp")
public class ApiController {

    @Autowired
    private HospitalService hospitalService;

    @Autowired
    private HospitalSetService hospitalSetService;
    
    //上传医院信息
    @PostMapping("/saveHospital")
    public Result saveHospital(HttpServletRequest request){
        //获取传递过来的医院信息
        Map<String, String[]> requestMap = request.getParameterMap();
        //将Map<String, String[]> 形式转换成Map<String, Object>方便后续使用
        Map<String, Object>  paramMap = HttpRequestHelper.switchMap(requestMap);

        //1、获取医院传递过来的签名,签名进行MD5加密
        String hospSign = (String)paramMap.get("sign");

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

        //3、把数据库拆线呢的签名进行加密
        String signKeyMD5 = MD5.encrypt(signKey);

        //3、判断签名是否一致
        if(!hospSign.equals(signKeyMD5)){
            throw new YyghException(ResultCodeEnum.SIGN_ERROR);
        }

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

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

7、集成测试

参考《医院接口模拟系统.docx》进行接口测试与数据上传,后续不做说明,需要测试时即可使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值