功能模块:尚医通(预约挂号平台、管理平台、接口系统)、医院系统(接口系统)
业务流程:
3、尚医通技术架构架构设计需要考虑的几个方面:
(资料图片)
可扩展性:系统功能会随着用户量的增加以及多变的互联网用户需求不断地扩展,因此考虑到系统的可扩展性的要求,需要使用微服务架构
,引入消息中间件
。性能:考虑访问频率,每个用户每天的访问次数。一般项目初始阶段用户的访问量可能并不大,如果考虑做运营推广,可能会迎来服务器访问量骤增,因此要考虑分布式部署
,引入缓存
。安全性: 系统的信息有一定的隐私性,例如用户的个人身份信息,因此使用账号密码管理
。另外涉及到身份证照片的上传,需要有加密和权限控制功能的文件服务器
。系统涉及第三方微信登录和微信支付,引入微信登录接口和支付接口
,确保登录和支付的安全。高可用:系统一旦宕机,将会带来不可挽回的损失,因此必须做负载均衡
,甚至是异地多活
这类复杂的方案。如果数据丢失,修复将会非常麻烦,只能靠人工逐条修复,这个很难接受,因此需要考虑存储高可靠
。我们需要考虑多种异常情况:机器故障、机房故障,针对机器故障,我们需要设计 MySQL 同机房主备
方案;针对机房故障,我们需要设计 MySQL 跨机房同步
方案。为了减轻MySQL服务器的访问压力,我们引入更灵活的MongoDB
数据库。成本:互联网程序的主要成本在于服务器成本、流量成本、存储成本、流媒体研发成本,中小型公司可以考虑使用云服务器和云服务
。系统中我们是用了阿里云OSS和阿里云市场短信。第02章-启动项目工程整个项目基于一个已经开发好的“通用权限系统”
进行二次开发,因此我们先将“通用权限系统”搭建并运行起来
资料:资料>权限系统>guigu_common_system.sql
mkdir -p /atguigu/syt/redis/{data,conf}
2.2、复制配置文件在 /atguigu/syt/redis/conf
目录中创建文件 redis.conf
,文件从
资料:资料>权限系统>redis-6.2.7.tar.gz
中解压获取
修改默认配置(从上至下依次):
#bind 127.0.0.1 #注释掉这部分,这是限制redis只能本地访问protected-mode no #默认yes,开启保护模式,限制为本地访问daemonize no #默认no,改为yes意为以守护进程方式启动,可后台运行,#注意!!!此处是no,否则redis无法通过配置文件启动
也可以直接从资料目录复制,这里是已经修改好的配置文件
资料:资料>权限系统>redis.conf
docker run -d --restart=always --name atguigu_syt_redis \-p 6379:6379 \-v /atguigu/syt/redis/conf/redis.conf:/redis.conf \-v /atguigu/syt/redis/data:/data \redis:6.2.7 \redis-server /redis.conf \--appendonly yes --requirepass "123456"
参数解释:
-d 后台运行-p 端口映射到主机的端口-v 将主机目录挂载到容器的目录redis-server --appendonly yes : 在容器执行redis-server启动命令,并打开appendonly持久化配置–requirepass :设置密码
常见问题:以下IPv4问题会导致无法远程链接redis服务
解决方案:
#修改配置文件:vim /usr/lib/sysctl.d/00-system.conf#追加net.ipv4.ip_forward=1#接着重启网络systemctl restart network
2.4、进入redis容器docker exec -it atguigu_syt_redis redis-cli
2.5、输入密码auth 123456
2.6、测试set name "xiaogu"
2.7、远程连接测试在本机使用客户端工具远程链接redis,测试是否能成功连接
3、运行后端项目3.1、启动后端Java项目资料:资料>权限系统>guigu-syt-parent.zip
将压缩包解压,并放在自己的工作目录下,启动前注意检查:
配置文件:修改application-dev.yml中MySQL和redis的相关参数
idea的Maven配置:配置到自己的Maven配置文件和本地仓库目录中
idea中配置的jdk版本:1.8.0_300以上(微信支付安全策略要求)
idea的项目编码:utf8
MySQL版本:8.0
3.2、测试后端Java项目访问Swagger测试页面:http://localhost:8800/doc.html
执行登录测试,并获取token:用户名是admin
,密码是111111
资料:资料>权限系统>guigu-syt-ui.zip
将压缩包解压,并放在自己的工作目录下,启动前注意检查:
node.js版本:v16.16.0执行以下命令启动项目
npm i #安装项目依赖模块npm run dev #运行程序
4.2、测试前端vue项目访问前端页面:http://localhost:9528/
5、项目结构介绍5.1、后端项目|-guigu-syt-parent:项目父节点,管理多个子模块|-common:公共模块父节点|-common-log:系统日志|-common-util:通用工具类|-model:实体类|-service-util:微服务通用配置|-spring-security:用户认证和授权|-service:微服务父节点|-service-system:认证和授权管理微服务
说明:model
模块中的com.atguigu.syt
是尚医通项目中的实体类
这里列出重要的目录和文件:
|-node_modules 下载的模块依赖|-public|-index.html 入口页面|-src|-api 后端api请求模块|-assets 公共资源文件|-components 通用组件|-layout 页面布局|-router 路由配置|-utils 通用工具|-request.js axios封装|-views 页面组件|-dashboard 首页面|-login 登录页面|-system 通用权限页面|-App.vue 根组件|-main.js 入口js|-settings.js 应用基本配置|-package.json 当前项目基本信息和依赖信息|-vue.config.js webpack相关配置
第03章-医院设置微服务1、需求当医院入驻尚医通平台后,尚医通管理员会为每个医院创建一条医院设置记录,这里会为每个医院分配一个唯一的医院编码,分配一个用于远程接口调用的密钥,并配置每个医院的远程接口主机地址,以及医院信息系统的联系人、联系方式等相关信息。只有平台为医院添加了医院设置信息,医院才可以上传医院基本信息、医院预约规则信息、医院科室信息、医院排班信息等内容到平台中。
1.1、医院设置列表1.2、医院设置表单2、创建数据库资料:资料>医院设置微服务>guigu_syt_hosp.sql
hosname:医院名称hoscode:医院编号(平台分配,全局唯一,api接口必填信息)api_url:医院接口调用的主机地址(如:预约下单,我们要调用该地址去医院下单)sign_key:双方api接口调用的签名key,由平台生成contacts_name:医院联系人姓名contacts_phone:医院联系人手机status:状态(锁定/解锁)
3、创建service-hosp模块在service下创建子模块,选择 maven类型的模块,输入模块名称service-hosp
,完成创建
创建后删除默认的主类Main.java
4、添加依赖在service-hosp中添加依赖:
com.atguigu model 1.0 com.atguigu service-util 1.0 com.atguigu spring-security 1.0 mysql mysql-connector-java org.springframework.boot spring-boot-starter-test test
5、代码生成器在service-util中添加代码生成器:
5.1、添加依赖 com.baomidou mybatis-plus-generator org.apache.velocity velocity-engine-core mysql mysql-connector-java provided
5.2、编写代码生成器在service-util的test目录中,创建包com.atguigu.syt
,
从资料中复制代码生成器
资料:资料>医院设置微服务>CodeGen.java
确认代码生成器中变量moduleName
的值为hosp
,以及数据源配置,然后运行程序
然后删除service-hosp微服务中的entity包,修改mapper层和service层引入的实体类,并引入model模块中的实体类
6、创建配置文件在service-hosp模块中resources目录下创建文件
application.yml
:
spring: application: name: service-hosp profiles: active: dev,redis
application-dev.yml
:
server: port: 8201mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl mapper-locations: classpath:com/atguigu/syt/hosp/mapper/xml/*.xmlspring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver password: 123456 url: jdbc:mysql://localhost:3306/guigu_syt_hosp?characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false username: root jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8
7、创建SpringBoot启动类在包com.atguigu.syt.hosp
中创建启动类ServiceHospApplication.java
package com.atguigu.syt.hosp;@SpringBootApplication@ComponentScan(basePackages = {"com.atguigu"})public class ServiceHospApplication { public static void main(String[] args) { SpringApplication.run(ServiceHospApplication.class, args); }}
8、实现基本CRUD简单的功能我们可以直接在controller中实现
8.1、编写Controller代码注意:将@RequestMapping路径前面添加 /admin
前缀
package com.atguigu.syt.hosp.controller.admin;@Api(tags = "医院设置管理")@RestController@RequestMapping("/admin/hosp/hospitalSet")public class AdminHospitalSetController { @Resource private HospitalSetService hospitalSetService; @ApiOperation(value = "根据id查询医院设置") @GetMapping("/getHospSet/{id}") public Result getById( @ApiParam(value = "医院设置id",required = true) @PathVariable Long id){ HospitalSet hospitalSet = hospitalSetService.getById(id); return Result.ok(hospitalSet); } @ApiOperation(value = "根据id删除医院设置") @DeleteMapping("/{id}") public Result removeById( @ApiParam(value = "医院设置id",required = true) @PathVariable Long id){ boolean result = hospitalSetService.removeById(id); if(result){ return Result.ok().message("删除成功"); }else{ return Result.fail().message("删除失败"); } } @ApiOperation(value = "新增医院设置") @PostMapping("/saveHospSet") public Result save( @ApiParam(value = "医院设置对象", required = true) @RequestBody HospitalSet hospitalSet){ //设置状态 1可用 0锁定 hospitalSet.setStatus(1); //生成签名秘钥 Random random = new Random(); hospitalSet.setSignKey(MD5.encrypt(System.currentTimeMillis()+""+random.nextInt(1000))); boolean result = hospitalSetService.save(hospitalSet); if(result){ return Result.ok().message("添加成功"); }else{ return Result.fail().message("添加失败"); } } @ApiOperation(value = "根据ID修改医院设置") @PutMapping("/updateHospSet") public Result updateById( @ApiParam(value = "医院设置对象", required = true) @RequestBody HospitalSet hospitalSet){ boolean result = hospitalSetService.updateById(hospitalSet); if(result){ return Result.ok().message("修改成功"); }else{ return Result.fail().message("修改失败"); } } @ApiOperation(value = "批量删除医院设置") //[1,2,3] @DeleteMapping("/batchRemove") public Result batchRemoveHospitalSet( @ApiParam(value = "id列表", required = true) @RequestBody List idList) { boolean result = hospitalSetService.removeByIds(idList); if(result){ return Result.ok().message("删除成功"); }else{ return Result.fail().message("删除失败"); } } @ApiOperation(value = "医院设置锁定和解锁") @PutMapping("/lockHospitalSet/{id}/{status}") public Result lockHospitalSet( @ApiParam(value = "医院设置id",required = true) @PathVariable Long id, @ApiParam(value = "状态", required = true) @PathVariable Integer status) { if(status != 0 && status != 1){ return Result.fail().message("非法数据"); } HospitalSet hospitalSet = new HospitalSet(); hospitalSet.setId(id); hospitalSet.setStatus(status); boolean result = hospitalSetService.updateById(hospitalSet); if(result){ return Result.ok().message("操作成功"); }else{ return Result.fail().message("操作失败"); } }}
8.2、Swagger测试注意:先登录,获取token,然后设置全局token
9、分页和条件查询复杂的功能我们需要添加service层
9.1、ControllerAdminHospitalSetController中添加分页方法
@ApiOperation("分页条件查询")@GetMapping("/{page}/{limit}")public Result pageList( @ApiParam(value = "页码",required = true) @PathVariable Long page, @ApiParam(value = "每页记录数",required = true) @PathVariable Long limit, @ApiParam(value = "查询对象",required = false) HospitalSetQueryVo hospitalSetQueryVo){ Page pageParam = hospitalSetService.selectPage(page, limit, hospitalSetQueryVo); return Result.ok(pageParam);}
9.2、Service接口:HospitalSetService
/** * 分页查询 * @param page 页码 * @param limit 每页记录数 * @param hospitalSetQueryVo 查询对象 * @return 分页对象 */Page selectPage(Long page, Long limit, HospitalSetQueryVo hospitalSetQueryVo);
实现:HospitalSetServiceImpl
@Overridepublic Page selectPage(Long page, Long limit, HospitalSetQueryVo hospitalSetQueryVo) { //分页参数 Page pageParam = new Page<>(page, limit); //查询参数 QueryWrapper queryWrapper = new QueryWrapper<>(); String hosname = hospitalSetQueryVo.getHosname(); queryWrapper.like(!StringUtils.isEmpty(hosname),"hosname", hosname); String hoscode = hospitalSetQueryVo.getHoscode(); queryWrapper.eq(!StringUtils.isEmpty(hoscode), "hoscode", hoscode); //执行查询 baseMapper.selectPage(pageParam, queryWrapper); return pageParam;}
第04章-统一日志1、Logback日志spring boot内部使用Logback
作为日志实现的框架。
通过日志查看程序的运行过程,运行信息,异常信息等
统一日志处理的目的:
将日志记录在文件中,方便运维和开发做错误排查文件日志需要做滚动输出(输出到更多的日志文件中),避免单日志体积过大,拖垮服务器可以方便的在开发环境和生产环境等环境中切换输出方式,例如在控制台和日志文件中灵活输出1.2、设置日志级别日志记录器(Logger)的行为是分等级的。如下表所示:
从高到低分为:ERROR、WARN、INFO、DEBUG、TRACE
可以在service-hosp的application-dev.yml文件中,通过以下配置设置日志级别
logging: level: root: info
1.3、测试日志的输出启动service-hosp微服务,可以看到微服务的启动日志在控制台上输出了info级别的内容
也可以修改成debug、error等其他级别查看日志输出情况
1.4、测试日志的打印在AdminHospitalSetController类上添加注解:
@Slf4j
添加测试方法:
@ApiOperation(value = "日志测试")@GetMapping("/log")public Result log(){ log.trace("getHospSet trace"); log.debug("getHospSet debug"); log.info("getHospSet info"); log.warn("getHospSet warn"); log.error("getHospSet error"); return Result.ok();}
在application-dev.yml文件中修改日志级别,可以看到日志的输出情况。
2、Logback日志文件可以创建独立的日志配置文件,配置更强大的日志功能
2.1、创建Logback日志文件在service-util的resources目录 中创建 logback-spring.xml
(默认日志文件的名字)
在logback-spring.xml中配置如下内容:
syt ${CONSOLE_LOG_PATTERN} ${charset}
启动service-hosp,微服务的启动信息在控制台按照CONSOLE_LOG_PATTERN
中设置的格式和颜色输出,并且输出的级别由root节点的level属性
指定
控制台日志只在开发环境下使用,生产环境下我们不使用控制台日志,而是需要将日志输出到文件中。
在logback-spring.xml中配置如下内容:
syt true ${logging.level} ${logging.position}${logging.path}/syt-log.log %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n ${charset} ${logging.position}${logging.path}/syt-log-%d{yyyy-MM-dd}.%i.log 1MB 30
在service-hosp的application-dev.yml文件中,通过以下配置设置日志级别和日志路径
logging: level: root: info file: path: hosp
所以控制台中将只会打印出Spring Boot的bannar之后就啥也不打印了,所有的启动信息都会被打印在日志文件syt-log.log中。
但是实际上我们不希望业务日志
中包括这些启动信息
。所以这个时候我们就需要通过logger标签来搞事情了。将上面的配置文件进行简单修改:将
2.4、只打印error的appender通过如下的方式设置
true ERROR ACCEPT DENY ${logging.position}${logging.path}/syt-error-log.log %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n ${charset} ${logging.position}${logging.path}/syt-error-log-%d{yyyy-MM-dd}.%i.log 1MB 30
2.5、完整的日志配置文件可以从资料文件夹中复制完整的日志配置文件到service-util中
资料:资料>医院设置微服务>logback-spring.xml
文件中添加了
修改service-hosp中的application.yml配置文件如下:则日志输出在控制台
spring: application: name: service-hosp profiles: active: dev,redis
修改service-hosp中的application.yml配置文件如下:则日志输出在文件中
spring: application: name: service-hosp profiles: active: prod,redis
在service-system中的application-dev中添加如下配置:
logging: level: root: info file: path: system
源码:https://gitee.com/dengyaojava/guigu-syt-parent
上一篇:他们在这里有什么特色内容
下一篇:最后一页
X 关闭
Copyright © 2015-2022 亚洲净水网版权所有 备案号:京ICP备2021034106号-51 联系邮箱:5 516 538 @qq.com