传智健康day04 预约管理-套餐管理

传智健康day04 预约管理-套餐管理,第1张

传智健康day04 预约管理-套餐管理 1. 图片存储方案 1.1 介绍

在实际开发中,我们会有很多处理不同功能的服务器。例如:

应用服务器:负责部署我们的应用

数据库服务器:运行我们的数据库

文件服务器:负责存储用户上传文件的服务器

分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。

常见的图片存储方案:

方案一:使用nginx搭建图片服务器

方案二:使用开源的分布式文件存储系统,例如Fastdfs、HDFS等

方案三:使用云存储,例如阿里云、七牛云等

1.2 七牛云存储

七牛云(隶属于上海七牛信息技术有限公司)是国内领先的以视觉智能和数据智能为核心的企业级云计 算服务商,同时也是国内知名智能视频云服务商,累计为 70 多万家企业提供服务,覆盖了国内80%网 民。围绕富媒体场景推出了对象存储、融合 CDN 加速、容器云、大数据平台、深度学习平台等产品、 并提供一站式智能视频云解决方案。为各行业及应用提供可持续发展的智能视频云生态,帮助企业快速 上云,创造更广阔的商业价值。

官网:https://www.qiniu.com/

通过七牛云官网介绍我们可以知道其提供了多种服务,我们主要使用的是七牛云提供的对象存储服务来 存储图片。

1.2.1 注册、登录

要使用七牛云的服务,首先需要注册成为会员。地址:https://portal.qiniu.com/signup

注册完成后就可以使用刚刚注册的邮箱和密码登录到七牛云:

登录成功后根据提示进行实名认证,实名认证成功后点击页面右上角管理控制台:

1.2.2 新建存储空间

要进行图片存储,我们需要在七牛云管理控制台新建存储空间。点击管理控制台首页对象存储下的立即 添加按钮,页面跳转到新建存储空间页面: 

 可以创建多个存储空间,各个存储空间是相互独立的。

1.2.3 查看存储空间信息

存储空间创建后,会在左侧的空间管理列表菜单中展示创建的存储空间名称,点击存储空间名称可以查看当前存储空间的相关信息

 1.2.4 开发者中心

可以通过七牛云提供的开发者中心学习如何 *** 作七牛云服务,地址:https://developer.qiniu.com/

 点击对象存储,跳转到对象存储开发页面,地址:https://developer.qiniu.com/kodo

 

 七牛云提供了多种方式 *** 作对象存储服务,本项目采用ava SDK方式,地址:https://developer.qiniu.com/kodo/1239/java

 使用Java SDK *** 作七牛云需要导入如下maven坐标:


  com.qiniu
  qiniu-java-sdk
  7.7.0
1.2.5 鉴权

Java SDK的所有的功能,都需要合法的授权。授权凭证的签算需要七牛账号下的一对有效的Access Key 和Secret Key,这对密钥可以在七牛云管理控制台的个人中心(https://portal.qiniu.com/user/key)获得,如下图:

1.2.6 Java SDK *** 作七牛云

本章节我们就需要使用七牛云提供的Java SDK完成图片上传和删除,我们可以参考官方提供的例子。

//构造一个带指定 Region 对象的配置类
Configuration cfg = new Configuration(Region.region0());
//...其他参数参考类注释
UploadManager uploadManager = new UploadManager(cfg);
//...生成上传凭证,然后准备上传
String accessKey = "your access key";
String secretKey = "your secret key";
String bucket = "your bucket name";
//如果是Windows情况下,格式是 D:\qiniu\test.png
String localFilePath = "/home/qiniu/test.png";
//默认不指定key的情况下,以文件内容的hash值作为文件名
String key = null;
Auth auth = Auth.create(accessKey, secretKey);
String upToken = auth.uploadToken(bucket);
try {
    Response response = uploadManager.put(localFilePath, key, upToken);
    //解析上传成功的结果
    DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
    System.out.println(putRet.key);
    System.out.println(putRet.hash);
} catch (QiniuException ex) {
    Response r = ex.response;
    System.err.println(r.toString());
    try {
        System.err.println(r.bodyString());
    } catch (QiniuException ex2) {
        //ignore
    }
}

//构造一个带指定 Region 对象的配置类
Configuration cfg = new Configuration(Region.region0());
//...其他参数参考类注释
String accessKey = "your access key";
String secretKey = "your secret key";
String bucket = "your bucket name";
String key = "your file key";
Auth auth = Auth.create(accessKey, secretKey);
BucketManager bucketManager = new BucketManager(auth, cfg);
try {
    bucketManager.delete(bucket, key);
} catch (QiniuException ex) {
    //如果遇到异常,说明删除失败
    System.err.println(ex.code());
    System.err.println(ex.response.toString());
}
1.2.7 封装工具类

为了方便 *** 作七牛云存储服务,我们可以将官方提供的案例简单改造成一个工具类,在我们的项目中直接使用此工具类来 *** 作就可以:

package com.itterence.utils;

import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;


public class QiniuUtils {
    public static String accessKey = "G78D_qC2JG3V9WBW9lxysK9OZeslRJtJZI85orM_";
    public static String secretKey = "-ptaWzGugFgUbFNBu8OWoSqbaTfiAPvdz9EJaLtr";
    public static String bucket = "itterence-health";

    public static void upload2Qiniu(String filePath,String fileName){
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.zone1());
        UploadManager uploadManager = new UploadManager(cfg);
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(filePath, fileName, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
        } catch (QiniuException ex) {
            Response r = ex.response;
            try {
                System.err.println(r.bodyString());
            } catch (QiniuException ex2) {
                //ignore
            }
        }
    }

    //上传文件
    public static void upload2Qiniu(byte[] bytes, String fileName){
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.zone1());
        //...其他参数参考类注释
        UploadManager uploadManager = new UploadManager(cfg);

        //默认不指定key的情况下,以文件内容的hash值作为文件名
        String key = fileName;
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(bytes, key, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            System.out.println(putRet.key);
            System.out.println(putRet.hash);
        } catch (QiniuException ex) {
            Response r = ex.response;
            System.err.println(r.toString());
            try {
                System.err.println(r.bodyString());
            } catch (QiniuException ex2) {
                //ignore
            }
        }
    }

    //删除文件
    public static void deleteFileFromQiniu(String fileName){
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.zone1());
        String key = fileName;
        Auth auth = Auth.create(accessKey, secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            bucketManager.delete(bucket, key);
        } catch (QiniuException ex) {
            //如果遇到异常,说明删除失败
            System.err.println(ex.code());
            System.err.println(ex.response.toString());
        }
    }
}

注:此处我遇到了maven依赖的问题,在test目录下import com.google.gson.Gson;没问题,在java目录中报红色错误,提示没有依赖,然后我查看maven工具内,这个包的状态为runtime,这就是无法编译问题所在

 最终在父工程pom.xml中 添加了com.google.code.gson包


    com.google.code.gson
    gson
    2.8.5
    compile

将此工具类放在health_common工程中,后续会使用到。

2. 新增套餐 2.1 需求分析

套餐其实就是检查组的集合,例如有一个套餐为“入职体检套餐”,这个体检套餐可以包括多个检查组:一般检查、血常规、尿常规、肝功三项等。所以在添加套餐时需要选择这个套餐包括的检查组。

套餐对应的实体类为Setmeal,对应的数据表为t_setmeal。套餐和检查组为多对多关系,所以需要中间表t_setmeal_checkgroup进行关联。

2.2 完善页面

套餐管理页面对应的是setmeal.html页面,根据产品设计的原型已经完成了页面基本结构的编写,现在 需要完善页面动态效果。

2.2.1 d出新增窗口

页面中已经提供了新增窗口,只是出于隐藏状态。只需要将控制展示状态的属性dialogFormVisible改为true接口显示出新增窗口。点击新建按钮时绑定的方法为handleCreate,所以在handleCreate方法中修改dialogFormVisible属性的值为true即可。同时为了增加用户体验度,需要每次点击新建按钮时清空表单输入项。

由于新增套餐时还需要选择此套餐包含的检查组,所以新增套餐窗口分为两部分信息:基本信息和检查 组信息,如下图:

新建按钮绑定单击事件,对应的处理函数为handleCreate 

新建
// 重置表单
resetForm() {
    this.formData = {};
    this.activeName='first';
    this.checkgroupIds = [];
    this.imageUrl = null;
},
// d出添加窗口
handleCreate() {
    this.dialogFormVisible = true;
    this.resetForm();
},
2.2.2 动态展示检查组列表

现在虽然已经完成了新增窗口的d出,但是在检查组信息标签页中需要动态展示所有的检查组信息列表数据,并且可以进行勾选。

具体 *** 作步骤如下:

(1)定义模型数据

tabledata:[],//添加表单窗口中检查组列表数据
checkgroupIds:[],//添加表单窗口中检查组复选框对应id

(2)动态展示检查组列表数据,数据来源于上面定义的tableData模型数据

    
    
        选择
        项目编码
        项目名称
        项目说明
    
    
    
    
        
            
        
        
        
        
    
    

(3)完善handleCreate方法,发送ajax请求查询所有检查组数据并将结果赋值给tableData模型数据用 于页面表格展示

// d出添加窗口
handleCreate() {
    this.dialogFormVisible = true;
    this.resetForm();
    axios.get("/checkgroup/findAll.do").then((res)=> {
        if(res.data.flag){
            this.tableData = res.data.data;
        }else{
            this.$message.error(res.data.message);
        }
    });
},

(4)分别在CheckGroupController、CheckGroupService、CheckGroupServiceImpl、 CheckGroupDao、CheckGroupDao.xml中扩展方法查询所有检查组数据

CheckGroupController:

//查询所有
@RequestMapping("/findAll")
public Result findAll(){
    List checkGroupList = checkGroupService.findAll();
    if(checkGroupList != null && checkGroupList.size() > 0){
        Result result = new Result(true, MessageConstant.QUERY_CHECKGROUP_SUCCESS);
        result.setData(checkGroupList);
        return result;
    }
    return new Result(false,MessageConstant.QUERY_CHECKGROUP_FAIL);
}

CheckGroupService:

List findAll();

CheckGroupServiceImpl:

public List findAll() {
    return checkGroupDao.findAll();
}

CheckGroupDao:

List findAll();

CheckGroupDao.xml:


	select * from t_setmeal
	
		where code = #{value} or name = #{value} or helpCode = #{value}
	
4. 定时任务组件Quartz 4.1 Quartz介绍

Quartz是Job scheduling(作业调度)领域的一个开源项目,Quartz既可以单独使用也可以跟spring框架整合使用,在实际开发中一般会使用后者。使用Quartz可以开发一个或者多个定时任务,每个定时任务可以单独指定执行的时间,例如每隔1小时执行一次、每个月第一天上午10点执行一次、每个月最后一天下午5点执行一次等。

官网:http://www.quartz-scheduler.org/

maven坐标:


    org.quartz-scheduler
    quartz
    2.2.1


    org.quartz-scheduler
    quartz-jobs
    2.2.1
4.2 Quartz入门案例

本案例基于Quartz和spring整合的方式使用。具体步骤:

(1)创建maven工程quartzdemo,导入Quartz和spring相关坐标,pom.xml文件如下



    4.0.0

    com.itterence
    quartz_demo
    1.0-SNAPSHOT

    
        8
        8
    

    
        
            org.springframework
            spring-context-support
            5.0.2.RELEASE
        
        
            org.springframework
            spring-tx
            5.0.2.RELEASE
        
        
            org.quartz-scheduler
            quartz
            2.2.1
        
        
            org.quartz-scheduler
            quartz-jobs
            2.2.1
        
    

(2)自定义一个Job

package com.itterence.jobs;

public class JobDemo {
    public void run(){
        System.out.println("job execute...");
    }
}

(3)提供Spring配置文件spring-jobs.xml,配置自定义Job、任务描述、触发器、调度工厂等



    
    
    
    
        
        
        
        
    
    
    
        
        
        
        
            0/10 * * * * ?
        
    
    
    
        
        
            
                
            
        
    

(4)编写main方法进行测试

package com.itterence;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("spring-jobs.xml");
    }
}

执行上面main方法观察控制台,可以发现每隔10秒会输出一次,说明每隔10秒自定义Job被调用一次。

4.3 cron表达式

上面的入门案例中我们指定了一个表达式:0/10 * * * * ?

这种表达式称为cron表达式,通过cron表达式可以灵活的定义出符合要求的程序执行的时间。本小节我们就来学习一下cron表达式的使用方法。如下图:

cron表达式分为七个域,之间使用空格分隔。其中最后一个域(年)可以为空。每个域都有自己允许的值和一些特殊字符构成。使用这些特殊字符可以使我们定义的表达式更加灵活。
下面是对这些特殊字符的介绍:
逗号(,):指定一个值列表,例如使用在月域上1,4,5,7表示1月、4月、5月和7月
横杠(-):指定一个范围,例如在时域上3-6表示3点到6点(即3点、4点、5点、6点)
星号(*):表示这个域上包含所有合法的值。例如,在月份域上使用星号意味着每个月都会触发
斜线(/):表示递增,例如使用在秒域上0/15表示每15秒
问号(?):只能用在日和周域上,但是不能在这两个域上同时使用。表示不指定
井号(#):只能使用在周域上,用于指定月份中的第几周的哪一天,例如6#3,意思是某月的第三个周五 (6=星期五,3意味着月份中的第三周)
L:某域上允许的最后一个值。只能使用在日和周域上。当用在日域上,表示的是在月域上指定的月份的最后一天。用于周域上时,表示周的最后一天,就是星期六
W:W 字符代表着工作日 (星期一到星期五),只能用在日域上,它用来指定离指定日的最近的一个工作日

4.4 cron表达式在线生成器

前面介绍了cron表达式,但是自己编写表达式还是有一些困难的,我们可以借助一些cron表达式在线生 成器来根据我们的需求生成表达式即可。

http://qqe2.com/cron

 5. 定时清理垃圾图片

前面我们已经完成了体检套餐的管理,在新增套餐时套餐的基本信息和图片是分两次提交到后台进行 *** 作的。也就是用户首先将图片上传到七牛云服务器,然后再提交新增窗口中录入的其他信息。如果用户 只是上传了图片而没有提交录入的其他信息,此时的图片就变为了垃圾图片,因为在数据库中并没有记 录它的存在。此时我们要如何处理这些垃圾图片呢?

解决方案就是通过定时任务组件定时清理这些垃圾图片。为了能够区分出来哪些图片是垃圾图片,我们 在文件上传成功后将图片保存到了一个redis集合中,当套餐数据插入到数据库后我们又将图片名称保存 到了另一个redis集合中,通过计算这两个集合的差值就可以获得所有垃圾图片的名称。

本章节我们就会基于Quartz定时任务,通过计算redis两个集合的差值找出所有的垃圾图片,就可以将 垃圾图片清理掉。 *** 作步骤:

(1)创建maven工程health_jobs,打包方式为war,导入Quartz等相关坐标



    
        health_parent
        com.itterence
        1.0-SNAPSHOT
    
    4.0.0

    health_jobs
    war

    
        8
        8
    
    
        
            com.itterence
            health_common
            1.0-SNAPSHOT
            compile
        
        
            com.itterence
            health_interface
            1.0-SNAPSHOT
        
        
            org.quartz-scheduler
            quartz
        
        
            org.quartz-scheduler
            quartz-jobs
        
    
    
        
            
                org.apache.tomcat.maven
                tomcat7-maven-plugin
                
                    
                    83
                    
                    /
                
            
        
    

(2)配置web.xml




    Archetype Created Web Application
    
    
        contextConfigLocation
        classpath*:applicationContext*.xml
    
    
        org.springframework.web.context.ContextLoaderListener
    

(3)配置log4j.properties

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout

(4)配置applicationContext-redis.xml




    
    
        
            200
        
        
            50
        
        
        
    
    
        
        
        
        
    

(5)配置applicationContext-jobs.xml



    
    
    
    

    
        
        
        
        
    
    
    
        
        
        
        
            
            0/10 * * * * ?
        
    
    
    
        
        
            
                
            
        
    

(6)创建ClearImgJob定时任务类

package com.itterence.jobs;

import com.itterence.constant.RedisConstant;
import com.itterence.utils.QiniuUtils;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.JedisPool;

import java.util.Set;


public class ClearImgJob {
    @Autowired
    private JedisPool jedisPool;
    public void clearImg(){
        //根据Redis中保存的两个set集合进行差值计算,获得垃圾图片名称集合
        Set set =
                jedisPool.getResource().sdiff(RedisConstant.SETMEAL_PIC_RESOURCES,
                        RedisConstant.SETMEAL_PIC_DB_RESOURCES);
        if(set != null){
            for (String picName : set) {
                //删除七牛云服务器上的图片
                QiniuUtils.deleteFileFromQiniu(picName);
                //从Redis集合中删除图片名称
                jedisPool.getResource().
                        srem(RedisConstant.SETMEAL_PIC_RESOURCES,picName);
            }
        }
    }

}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5711086.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存