醫院管理API & 服務註冊與發現
尚硅谷Spring筆記-08
醫院管理系統
- hospital-manage醫院管理系統,是一個已經完成的模組,功能是提供給醫院方操作,讓醫院管理人員上傳醫院的科室、排班資訊等等的一個小系統
- 我們的項目是預約掛號平台,要實現求診者與醫院的配對
- 現在就要模擬實際業務,參考提供的API文檔完成對接
連接MongoDB
練習點,這邊把醫院方上傳的資料存到mongoDB
- 回到
service-hosp
模組,先去application.properties
設定資料庫連線地址 - 建立接口繼承
MongoRepository
@Repository
public interface HospitalRepository extends MongoRepository<Hospital, String> {}
- 建立
HospitalServiceImpl
接口與實現類、ApiController
開始對接API
上傳醫院
- 控制層知識點:
request.getParameterMap()
拿到的是String[],最好轉成Obj方便後續操作- 這邊用了base64編碼傳了一張圖片,"+“變成了” “空白要還原
- 之後用
<img src="data:image/png;base64,編碼串"/>
可以把圖片還原顯示出來
@ApiOperation("上傳醫院")
@PostMapping("saveHospital")
public Result saveHospital(HttpServletRequest request) {
Map<String, String[]> parameterMap = request.getParameterMap();
// 調用工具類把map中的string[]轉成obj
Map<String, Object> stringObjectMap = HttpRequestHelper.switchMap(parameterMap);
// base64編碼傳送過程中把"+"變成了" "空白,要轉換回來
String logoData = (String) stringObjectMap.get("logoData");
logoData = logoData.replaceAll(" ", "+");
stringObjectMap.put("logoData", logoData);
return hospitalService.save(stringObjectMap) ? Result.ok() : Result.build(230, "醫院編號已存在,修改請聯絡工程師");
}
- 服務層
- 他教學這邊用
alibaba.fastjson
包把stringObjectMap
轉成JSON
,再從JSON轉回Bean,把我看暈了 - 幹嘛不乾脆用
apache.commons.beanutils
的populate
- 後來發現mybatis+自帶
BeanUtils.mapToBean
也可以,還少導依賴 - MD5加密跟修改上傳也把我看暈了,他教學這裡有點瑕疵,反正原理能懂,暫時跳過吧
- 他教學這邊用
@Override
public boolean save(Map<String, Object> stringObjectMap) {
// 將map轉成Hospital實體類物件
// String string = JSONObject.toJSONString(stringObjectMap);
// Hospital hospital = JSONObject.parseObject(string, Hospital.class);
Hospital hospital = BeanUtils.mapToBean(stringObjectMap, Hospital.class);
// 判斷是否已存在
String hoscode = hospital.getHoscode();
Hospital hospitalExist = hospitalRepository.getHospitalByHoscode(hoscode);
/* TODO 這裡有bug,他設定hoscode是唯一,但是又不標記成mongo的Id,物件沒有mongo的Id作為屬性,
就沒辦法靠同Id視為更新的save去更新,永遠只會說重複不給存報錯,如果拿掉不重複標記,
就變成一直存成新物件,修這個要從model層去改
而MD5加密驗證的部分,覺得這邊他教的太混亂,應該寫在service層
原理懂就好,就醫院方API把key用MD5加密傳過來,平台方去醫院設定mysql也抓那個key
然後執行一樣的MD5加密,驗證是否相同,利用MD5不可逆推(暴力哈希碰撞除外)特性
實現安全驗證
*/
if (hospitalExist == null) {
// 新物件
hospital.setStatus(0);
hospital.setCreateTime(new Date());
hospital.setUpdateTime(new Date());
hospital.setIsDeleted(0);
hospitalRepository.save(hospital);
return true;
} else {
// 已存在,要修改
return false;
}
}
查詢醫院
- 毫無難度,利用Repository自動生成的方法,用Hoscode往mongoDB查找出對應的Hospital物件丟回去就完了
@ApiOperation("查詢醫院")
@PostMapping("hospital/show")
public Result showHospital(HttpServletRequest request) {
Map<String, String[]> parameterMap_0 = request.getParameterMap();
// 調用工具類把map中的string[]轉成obj
Map<String, Object> parameterMap = HttpRequestHelper.switchMap(parameterMap_0);
String hoscode = (String) parameterMap.get("hoscode");
return Result.ok(hospitalService.showHospital(hoscode));
}
科室
- 控制層,注意Page是spring框架的
@ApiOperation("上傳科室")
@PostMapping("saveDepartment")
public Result saveDepartment(HttpServletRequest request) {
Map<String, String[]> parameterMap_0 = request.getParameterMap();
Map<String, Object> parameterMap = HttpRequestHelper.switchMap(parameterMap_0);
return departmentService.save(parameterMap) ? Result.ok() : Result.build(230, "醫院科室編號已存在,修改請聯絡工程師");
}
@ApiOperation("查詢科室")
@PostMapping("department/list")
public Result findDepartment(HttpServletRequest request) {
Map<String, String[]> parameterMap_0 = request.getParameterMap();
Map<String, Object> parameterMap = HttpRequestHelper.switchMap(parameterMap_0);
// 獲取醫院編號
String hoscode = (String) parameterMap.get("hoscode");
// 獲取當前頁 和 每頁記錄數,沒指定(為空)就是1跟10
int page = StringUtils.isEmpty(parameterMap.get("page")) ? 1 : Integer.parseInt((String) parameterMap.get(
"page"));
int limit = StringUtils.isEmpty(parameterMap.get("limit")) ? 10 : Integer.parseInt((String) parameterMap.get(
"limit"));
DepartmentQueryVo departmentQueryVo = new DepartmentQueryVo();
departmentQueryVo.setHoscode(hoscode);
// 調用service方法
Page<Department> pageModel = departmentService.findPageDepartment(page, limit, departmentQueryVo);
return Result.ok(pageModel);
}
@ApiOperation("刪除科室")
@PostMapping("department/remove")
public Result removeDepartment(HttpServletRequest request) {
Map<String, String[]> parameterMap_0 = request.getParameterMap();
Map<String, Object> parameterMap = HttpRequestHelper.switchMap(parameterMap_0);
// 醫院編號 和 科室編號
String hoscode = (String) parameterMap.get("hoscode");
String depcode = (String) parameterMap.get("depcode");
if (depcode == null || hoscode == null) {
return Result.build(230, "醫院或科室編號不存在");
}
departmentService.remove(hoscode, depcode);
return Result.ok();
}
- 服務層,知識重點在條件查詢與頁數
@Service
public class DepartmentServiceImpl implements DepartmentService {
@Autowired
private DepartmentRepository departmentRepository;
@Override
public boolean save(Map<String, Object> parameterMap) {
Department department = BeanUtils.mapToBean(parameterMap, Department.class);
// 根據醫院編號 和 科室編號查詢
Department departmentExist = departmentRepository.
getDepartmentByHoscodeAndDepcode(department.getHoscode(), department.getDepcode());
if (departmentExist == null) {
department.setCreateTime(new Date());
department.setUpdateTime(new Date());
departmentRepository.save(department);
return true;
}
return false;
}
@Override
public Page<Department> findPageDepartment(int page, int limit, DepartmentQueryVo departmentQueryVo) {
// 創建Pageable,設置當前頁和每頁記錄數,0是第一頁
Pageable pageable = PageRequest.of(page - 1, limit);
// 查詢用VO,所以要先造一個department去承接屬性
Department department = new Department();
org.springframework.beans.BeanUtils.copyProperties(departmentQueryVo, department);
// 創建Example設定查詢條件
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
.withIgnoreCase(true);
Example<Department> example = Example.of(department, matcher);
Page<Department> all = departmentRepository.findAll(example, pageable);
return all;
}
@Override
public void remove(String hoscode, String depcode) {
// 根據醫院編號 和 科室編號查詢
Department department = departmentRepository.getDepartmentByHoscodeAndDepcode(hoscode, depcode);
if (department != null) {
// 調用方法刪除
departmentRepository.deleteById(department.getId());
}
}
}
班表
- 類似的就不重複,小結操作MongoDB的流程:
- 建立對應的Bean,有要條件查詢的可以建立VO
- 後來查了一下這算是開發規範,前端用VO後端用POJO
- 造xxxRepository介面繼承MongoRepository<bean, String>,記得註解
@Repository
- 造service層介面與實現類,實現類記得註解
@Service
- 造controller對接API,oooMapping(“URL”)
- 建立對應的Bean,有要條件查詢的可以建立VO
服務註冊中心
- 接著要繼續完成預約平台的後台系統,這邊需要橫跨多個模組查詢資料,例如醫院設定 + 字典檔模組
- 微服務架構之下,當啟動多個Spring服務要讓他們彼此能溝通,就需要依靠服務註冊與發現
- 常見的組合有:
- Spring Cloud Eureka + Spring Cloud Config
- Zookeeper + dubbo
- Consul
- 這邊使用Nacos,優勢在於註冊與配置二合一,簡單
Nacos前置
用docker啟動
# 拉映像
docker pull nacos/nacos-server
# 啟動容器
docker run --env MODE=standalone --name nacos -d -p 8848:8848 nacos/nacos-server
--env
配置環境MODE=standalong
單節點--name nacos
映象名稱為nacos-d
背景啟動- 預設網址為
localhost:8848/nacos
,帳號密碼都是nacos
- 通常為了持久化會搭配資料庫啟動,把服務資訊寫到資料庫例如mysql中,這邊先用內建的
Java部分
- pom.xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
- application.properties
# nacos服務地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
- 啟動類上加註解
- 小竅門: 在IDEA下面Service那邊點兩下就能快速找到
@EnableDiscoveryClient
- 設定完重啟服務就完成註冊了,可以在列表中看到
後台模組
- 接著回頭到平台的後台管理,在後台要能看到醫院方上傳來的科室、班表資料那些,先開始搭建後端
- 他教學的模組分類與命名真的忍不住要吐槽,甚麼hos、hosp、hospital、hospitalSet全都寫在一起辨識度有夠差,等整個搭完我一定要全部重新理一遍
- 不行了,這個項目差點把我做吐了,先停在P84,決定先去練谷粒商城,有機會再回來填坑吧
上次修改於 2022-01-18