首页 > 编程语言 >尚医通-day03【数据字典详细步骤】(内附源码)

尚医通-day03【数据字典详细步骤】(内附源码)

时间:2023-06-12 19:35:24浏览次数:49  
标签:cmn 缓存 尚医通 day03 region list 源码 public regionList

第01章-nacos和gateway的引入

1、引入nacos

1.1、启动nacos服务

资料:资料>数据字典微服务>nacos-server-1.4.2.zip

将资料中的nacos压缩包解压到非中文目录下,然后执行以下命令,单机启动nacos

startup.cmd -m standalone

访问:http://localhost:8848/nacos

用户名密码:nacos/nacos

1.2、引入依赖

service的pom.xml中配置Nacos客户端依赖

<dependencies>
    <!--服务注册-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

1.3、添加服务配置

配置application-dev.yml,在每个微服务模块中添加注册Nacos服务的配置信息

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

1.4、启动微服务

启动微服务,并查看nacos的服务列表

image-20230209165348351

2、引入微服务网关

2.1、创建微服务网关

image-20230315151724137

2.2、pom.xml引入依赖

在server-gateway中引入依赖

<dependencies>
    <!-- 网关 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!-- 服务注册 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

2.3、创建启动类

package com.atguigu.syt.gateway;

@SpringBootApplication
public class ServerGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServerGatewayApplication.class, args);
    }
}

2.4、配置路由转发

在server-gateway模块中resources目录下创建文件

application.yml

spring:
  application:
    name: server-gateway
  profiles:
    active: dev

application-dev.yml

server:
  port: 8200
spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: service-system
          predicates: Path=/*/system/**
          uri: lb://service-system
        - id: service-hosp
          predicates: Path=/*/hosp/**
          uri: lb://service-hosp
        - id: service-cmn
          predicates: Path=/*/cmn/**
          uri: lb://service-cmn
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

3、配置前端环境

3.1、修改代理配置

更改文件:vue.config.js,将target改到网关地址

proxy: {
  '/dev-api': { // 匹配所有以 '/dev-api'开头的请求路径
    target: 'http://localhost:8200',
    changeOrigin: true, // 支持跨域
    pathRewrite: { // 重写路径: 去掉路径中开头的'/dev-api'
      '^/dev-api': ''
    }
  }
}

3.2、重启程序

重启后端程序测试

第02章-数据字典列表

页面预览

image-20230210203119144

1、后端接口

1.1、创建数据库

资料:资料>数据字典微服务>guigu_syt_cmn.sql

1.2、创建service-cmn微服务

image-20230315153520921

1.3、添加依赖

在service-cmn中添加依赖:

<dependencies>
    <!--实体-->
    <dependency>
        <groupId>com.atguigu</groupId>
        <artifactId>model</artifactId>
        <version>1.0</version>
    </dependency>

    <!--服务通用配置-->
    <dependency>
        <groupId>com.atguigu</groupId>
        <artifactId>service-util</artifactId>
        <version>1.0</version>
    </dependency>

    <!--自定义安全模块-->
    <dependency>
        <groupId>com.atguigu</groupId>
        <artifactId>spring-security</artifactId>
        <version>1.0</version>
    </dependency>

    <!--mysql驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!-- 单元测试 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

1.4、使用代码生成器

找到service-util模块中的代码生成器,修改moduleName为cmn,并执行,然后删除entity包,相关类中引入model模块中的类

1.5、创建配置文件

在server-cmn模块中resources目录下创建文件

application.yml

spring:
  application:
    name: service-cmn
  profiles:
    active: dev,redis

application-dev.yml

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:com/atguigu/syt/cmn/mapper/xml/*.xml
server:
  port: 8202
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    password: 123456
    url: jdbc:mysql://localhost:3306/guigu_syt_cmn?characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false
    username: root
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    
logging:
  level:
    root: info
  file:
    path: cmn

1.6、创建启动类

package com.atguigu.syt.cmn;

@SpringBootApplication
@ComponentScan(basePackages = {"com.atguigu"})
public class ServiceCmnApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceCmnApplication.class, args);
    }
}

1.7、Controller

package com.atguigu.syt.cmn.controller.admin;

@Api(tags = "数据字典")
@RestController
@RequestMapping("/admin/cmn/dict")
public class AdminDictController {

    @Resource
    private DictService dictService;

    @ApiOperation(value = "获取全部数据字典")
    @GetMapping(value = "/findAllDictList")
    public Result<List<DictTypeVo>> findAllDictList() {
        List<DictTypeVo> list = dictService.findAllDictList();
        return Result.ok(list);
    }
}

1.8、Service

接口:DictService

/**
     * 获取数据字典嵌套列表
     * @return
     */
List<DictTypeVo> findAllDictList();

实现:DictServiceImpl

@Resource
private DictTypeService dictTypeService;

@Override
public List<DictTypeVo> findAllDictList() {

    //获取数据字典类型列表
    List<DictType> dictTypeList = dictTypeService.list();
    //获取数据字典列表
    List<Dict> dictList = this.list();

    List<DictTypeVo> dictTypeVoList = new ArrayList<>();
    //遍历数据字典类型列表
    dictTypeList.forEach(dictType -> {

        DictTypeVo dictTypeVo = new DictTypeVo();
        dictTypeVo.setId("parent-" +dictType.getId());
        dictTypeVo.setName(dictType.getName());

        List<Dict> subDictList = 
            dictList.stream().filter(dict -> dict.getDictTypeId().longValue() == dictType.getId().longValue()).collect(Collectors.toList());

        List<DictVo> children = new ArrayList<>();
        subDictList.forEach(dict -> {
            DictVo dictVo = new DictVo();
            dictVo.setId("children-" + dict.getId());
            dictVo.setName(dict.getName());
            dictVo.setValue(dict.getValue());
            children.add(dictVo);
        });
        dictTypeVo.setChildren(children);
        dictTypeVoList.add(dictTypeVo);
    });

    return dictTypeVoList;
}

2、前端页面

2.1、创建vue组件

在src/views/syt文件夹下创建cmn/dict/list.vue文件

<template>
  <div class="app-container">
    数据字典列表
  </div>
</template>

2.2、添加路由

静态路由:修改router/index.js文件

  {
    path: '/cmn',
    component: Layout,
    redirect: '/cmn/dict/list',
    name: 'BaseInfo',
    meta: { title: '基础数据', icon: 'el-icon-s-help' },
    alwaysShow: true,
    children: [
      {
        path: 'dict/list',
        name: '数据字典',
        component: () => import('@/views/syt/cmn/dict/list'),
        meta: { title: '数据字典', icon: 'el-icon-s-unfold' }
      },
    ]
  },

动态路由:

添加菜单:

image-20230315160404935

添加菜单项:

image-20230315160803695

2.3、定义api接口

创建文件 src/api/syt/dict.js

import request from '@/utils/request'
const apiName = '/admin/cmn/dict'

export default {

  findAllDictList() {
    return request({
      url: `${apiName}/findAllDictList`,
      method: 'get'
    })
  }
}

2.4、list.vue页面

cmn/dict/list.vue

<template>
  <div class="app-container">
    <!-- 数据字典列表 -->
    <el-table
      v-loading="listLoading"
      :data="list"
      element-loading-text="数据加载中"
      row-key="id"
      border
    >
      <el-table-column label="名称" prop="name" />
      <el-table-column label="ID" prop="id" />
      <el-table-column label="值" prop="value" />
    </el-table>
  </div>
</template>
<script>
import dictApi from '@/api/syt/dict'

export default {
  // 定义数据
  data() {
    return {
      listLoading: true, // 是否显示loading信息
      list: [],
    }
  },

  // 当页面加载时获取数据
  created() {
    this.fetchData()
  },

  methods: {
    // 调用api层获取数据库中的数据
    fetchData() {
      dictApi.findAllDictList().then((response) => {
        this.list = response.data
        this.listLoading = false
      })
    },
  },
}
</script>

第03章-地区列表

页面预览

image-20230210203214884

1、后端接口

1.1、Controller

package com.atguigu.syt.cmn.controller.admin;

@Api(tags = "地区")
@RestController
@RequestMapping("/admin/cmn/region")
public class AdminRegionController {

    @Resource
    private RegionService regionService;

    @ApiOperation(value = "根据上级code获取子节点数据列表")
    @ApiImplicitParam(name = "parentCode", value = "上级节点code", required = true)
    @GetMapping(value = "/findRegionListByParentCode/{parentCode}")
    public Result<List<Region>> findRegionListByParentCode(
            @PathVariable String parentCode) {
        List<Region> list = regionService.findRegionListByParentCode(parentCode);
        return Result.ok(list);
    }
}

1.2、Service

接口:RegionService

/**
     * 根据上级地区code获取地区列表
     * @param parentCode
     * @return
     */
List<Region> findRegionListByParentCode(String parentCode);

实现:RegionServiceImpl

@Override
public List<Region> findRegionListByParentCode(String parentCode) {

    LambdaQueryWrapper<Region> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(Region::getParentCode, parentCode);

    List<Region> regionList = baseMapper.selectList(queryWrapper);
    regionList.forEach(region -> {
        boolean isHasChildren = region.getLevel().intValue() < 3 ? true : false;
        region.setHasChildren(isHasChildren);
    });
    return regionList;
}

2、前端页面

2.1、创建vue组件

在src/views/syt文件夹下创建cmn/region/list.vue文件

<template>
  <div class="app-container">
    地区列表
  </div>
</template>

2.2、添加路由

静态路由:修改router/index.js文件,在基础数据下添加子节点

{
  path: 'region/list',
  name: '地区管理',
  component: () => import('@/views/syt/cmn/region/list'),
  meta: { title: '地区管理', icon: 'table' }
}

动态路由:

添加菜单项目:

image-20230315163044657

2.3、定义api接口

创建文件 src/api/syt/region.js

import request from '@/utils/request'
const apiName = '/admin/cmn/region'

export default {
  findRegionListByParentCode(parentCode) {
    return request({
      url: `${apiName}/findRegionListByParentCode/${parentCode}`,
      method: 'get'
    })
  }
}

2.4、list.vue页面

cmn/region/list.vue

<template>
  <div class="app-container">

    <el-table
      v-loading="listLoading"
      :data="list"
      element-loading-text="数据加载中"
      :load="getChildren"
      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
      style="width: 100%;margin-top: 10px;"
      row-key="id"
      border
      lazy>

      <el-table-column label="名称" align="left">
        <template slot-scope="scope">
          <span>{{ scope.row.name }}</span>
        </template>
      </el-table-column>
      <el-table-column label="地区编码" >
        <template slot-scope="{row}">
          {{ row.code }}
        </template>
      </el-table-column>
      <el-table-column label="地区级别" align="left">
        <template slot-scope="scope">
          <span>{{ scope.row.level }}</span>
        </template>
      </el-table-column>
    </el-table>

  </div>
</template>
<script>
import regionApi from '@/api/syt/region'

export default {

  // 定义数据
  data() {
    return {
      listLoading: true,  
      list: [],
    }
  },

  // 当页面加载时获取数据
  created() {
    this.fetchData()
  },

  methods: {
    // 调用api层获取数据库中的数据
    fetchData() {
      console.log('加载列表')
      regionApi.findRegionListByParentCode('0').then(response => {
        this.list = response.data
        console.log(this.list)
        this.listLoading = false
      })
    },

    getChildren(tree, treeNode, resolve) {
      debugger
      regionApi.findRegionListByParentCode(tree.code).then(response => {
        resolve(response.data)
      })
    },
  }
}
</script>

第04章-Redis

可以将地区列表的数据放入redis缓存,帮助提高页面的加载速度

1、使用缓存

1.1、RegionServiceImpl

@Resource
private RedisTemplate redisTemplate;

@Override
public List<Region> findRegionListByParentCode(String parentCode) {

    //先查询redis中是否存在dictList
    List<Region> regionList = null;
    try {
        regionList = (List<Region>)redisTemplate.opsForValue().get("regionList:" + parentCode);
        if(regionList != null){
            return regionList;
        }
    } catch (Exception e) {
        log.error("redis服务器异常:get regionList");
    }

    LambdaQueryWrapper<Region> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(Region::getParentCode, parentCode);

    regionList = baseMapper.selectList(queryWrapper);
    regionList.forEach(region -> {
        boolean isHasChildren = region.getLevel().intValue() < 3 ? true : false;
        region.setHasChildren(isHasChildren);
    });

    try {
        //将数据存入redis
        redisTemplate.opsForValue().set("regionList:" + parentCode, regionList, 5, TimeUnit.MINUTES);
    } catch (Exception e) {
        log.error("redis服务异常:set regionList");
    }
    return regionList;
}

1.2、测试

测试获取数据:

第一次查询从MySQL数据库获取,第二次查询从Redis获取

2、Spring Cache

2.1、简介

1、Spring Cache是Spring提供的一个缓存框架。

2、Spring Cache利用了AOP,实现了基于注解的缓存功能,业务代码不用关心底层是使用了什么缓存框架,只需要简单地加一个注解,就能实现缓存功能,从而减少对代码的入侵。

3、由于市面上的缓存工具实在太多,SpringCache框架还提供了CacheManager接口,可以降低对各种缓存框架的耦合。

2.2、开启缓存

在service-util模块的RedisConfig类上添加注解

@EnableCaching

2.3、JSON序列化方案

RedisConfig

@Bean
public CacheManager cacheManager(LettuceConnectionFactory connectionFactory) {

    //定义序列化器
    GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();


    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
        //过期时间600秒
        .entryTtl(Duration.ofSeconds(600))
        // 配置序列化
        .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(genericJackson2JsonRedisSerializer));

    RedisCacheManager cacheManager = RedisCacheManager.builder(connectionFactory)
        .cacheDefaults(config)
        .build();
    return cacheManager;
}

3、Spring Cache 常用注解

3.1、@Cacheable

作用:在方法执行前查看是否有缓存对应的数据,如果有直接返回数据,如果没有,则调用方法获取数据返回,并缓存起来。

RegionServiceImpl

    /**
     * @Cacheable:
     * 在方法执行前查看是否有缓存对应的数据,
     * 如果有直接返回数据,如果没有,则调用方法获取数据返回,并缓存起来。
     * 
     * value:缓存的名字
     * key:缓存的key
     * unless:条件符合则不缓存,是对出参进行判断,出参用#result表示
     *
     * @param parentCode
     * @return
     */
@Override
@Cacheable(value = "regionList", key = "#parentCode", unless="#result.size() == 0")
public List<Region> findRegionListByParentCode(String parentCode) {

    //先查询redis中是否存在dictList
    LambdaQueryWrapper<Region> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(Region::getParentCode, parentCode);

    List<Region> regionList = baseMapper.selectList(queryWrapper);
    regionList.forEach(region -> {
        boolean isHasChildren = region.getLevel().intValue() < 3 ? true : false;
        region.setHasChildren(isHasChildren);
    });

    return regionList;
}

3.2、@CachePut

作用:将方法的返回值放到缓存中

接口:RegionService

/**
     * 测试 @CachePut
     * @param region
     * @return
     */
Region saveRegionWithCacheManager(Region region);

实现:RegionServiceImpl

/**
     * 作用:将方法的返回值放到缓存中
     * @param region
     * @return
     */
@Override
@CachePut(value = "regionTest", key = "#region.id")
public Region saveRegionWithCacheManager(Region region) {
    baseMapper.insert(region);
    return region;
}

测试:在service-cmn的test目录中创建测试用例RedisTest

package com.atguigu.syt.cmn.redis;

@SpringBootTest
public class RedisTest {

    @Resource
    private RegionService regionService;

    @Test
    public void testSaveRegionWithCacheManager() {
        Region region = new Region();
        region.setName("test");
        regionService.saveRegionWithCacheManager(region);
    }
}

3.3、@CacheEvict

作用:执行方法体,删除缓存

接口:RegionService

/**
     * 测试 @CacheEvict
     * @param id
     */
void deleteRegionWithCacheManager(Long id);

实现:RegionServiceImpl

/**
     * 作用:执行方法体,删除缓存
     * @param id
     */
@Override
@CacheEvict(value = "regionTest", key = "#id")
public void deleteRegionWithCacheManager(Long id) {
    baseMapper.deleteById(id);
}

测试:RedisTest

@Test
public void testDeleteRegionWithCacheManager() {
    regionService.deleteRegionWithCacheManager(3712L);//刚刚插入的测试数据的id
}

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

标签:cmn,缓存,尚医通,day03,region,list,源码,public,regionList
From: https://www.cnblogs.com/deyo/p/17475898.html

相关文章

  • 尚医通-day05【MongoDB详细步骤】(内附源码)
    第01章-MongoDB1、安装和启动(docker方式)1.1、拉取镜像dockerpullmongo:4.4.81.2、创建和启动容器dockerrun-d--restart=always-p27017:27017--nameatguigu_syt_mongo-v/atguigu/syt/mongo/data/db:/data/dbmongo:4.4.8--auth常见问题:以下IPv4问题会导致无法......
  • 尚医通-day07【医院管理详细步骤】(内附源码)
    页面预览列表页批量导入数据为了方便测试,我们可以将更多的医院信息数据批量导入到系统中。将资料中的json数据和测试用例复制到项目中,然后执行测试用例即可资料:资料>批量导入医院数据第01章-医院列表信息1、医院列表1.1、Controller在service-hosp中创建AdminHospitalCo......
  • 尚医通-day06【医院模拟系统接口详细步骤】(内附源码)
    第01章-医院系统1、业务功能描述资料:资料>医院模拟系统>尚医通API接口文档.docx1.1、平台方参考《尚医通API接口文档.docx》进行业务接口的开发,接收医院方的接口调用,将医院信息、科室信息、排班信息等数据存入MongoDB。1.2、医院方每个医院有自己的业务平台,需参考《尚医通AP......
  • 尚医通-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源码可以在......