集群项目页面静态化

有的页面访问人数很多,但是在一定时间段内不会改变(数据没变化).页面静态化.

好处:
①降低数据库或缓存压力
②提高响应速度,增强用户体验.

页面静态化这是一种方案,而模板技术是实现这种方案的技术。
静态页面=模板(结构)+数据(内容)

单体项目方案分析

在这里插入图片描述

集群项目方案分析

在这里插入图片描述

技术点:

velocity + rabbitMq + Nosql(redis) + Dfs(fastdfs)

课程主页静态化实现

(1)准备模板
在这里插入图片描述 (2)准备模块:hrm-course-service-2020

Pom

<!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity -->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity</artifactId>
    <version>1.7</version>
</dependency>

导入
在这里插入图片描述
测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = CouseServiceApplication2020.class)
public class ICourseTypeServiceTest {

    @Autowired
    private ICourseTypeService courseTypeService;
    @Test
    public void testVelocityTmplate() {

        //数据+模板=静态页面
        Map<String,Object> model = new HashMap<>();
        model.put("staticRoot","D:\\0924\\2020-02-24-hrm-课程中心-课程主站-页面静态化实现\\resources\\home");
        model.put("courseTypes",courseTypeService.treeData(0L));
        VelocityUtils.staticByTemplate(model,
                "D:\\0924\\2020-02-24-hrm-课程中心-课程主站-页面静态化实现\\resources\\home\\home.vm",
                "D:\\0924\\2020-02-24-hrm-课程中心-课程主站-页面静态化实现\\resources\\home\\home.vm"+".html");
    }

(3)创建前台触发页面

(4)课程模块,初始化课程管理首页


测试方法
//初始化课程管理首页
    @Test
    public void testInitCourseSiteIndex()throws Exception{
        courseTypeService.InitCourseSiteIndex();
}



@Autowired
    private PageConfigClient pageConfigClient;
    @Override
    public void InitCourseSiteIndex() {
        //1 准备模板,并且上传fastdfs
        //2存放数据到redis
        List<CourseType> courseTypes = queryTypeTree(0L);
        String dataKey = "courseTypes";
        redisClient.set(dataKey, JSONArray.toJSONString(courseTypes));
        //3调用静态化接口产生静态页面,并且放入fastdfs
        String pageName = "CourseIndex";
        //本来应该通过PageName获取page后设置pageconfig传递,由于数据在查询端,还不如直接传入pageName到那边查询.
        Map<String,String> map = new HashMap<>();
        map.put("dataKey",dataKey);
        map.put("pageName",pageName);
        pageConfigClient.staticPage(map);
        //4往消息队列放一个消息,让pageAgent来下载静态页面
    }


 @Override
    public boolean insert(CourseType entity) {
        courseTypeMapper.insert(entity);
        List<CourseType> courseTypes = queryTypeTree(0L);
        courseTypeCache.setCourseTypes(courseTypes);

        //同步页面静态化
        this.InitCourseSiteIndex();
        return true;
    }

    @Override
    public boolean deleteById(Serializable id) {
        courseTypeMapper.deleteById(id);
        List<CourseType> courseTypes = queryTypeTree(0L);
        courseTypeCache.setCourseTypes(courseTypes);

        //同步页面静态化
        this.InitCourseSiteIndex();
        return true;
    }

    @Override
    public boolean updateById(CourseType entity) {
        courseTypeMapper.updateById(entity);
        List<CourseType> courseTypes = queryTypeTree(0L);
        courseTypeCache.setCourseTypes(courseTypes);

        //同步页面静态化
        this.InitCourseSiteIndex();
        return true;
    }

(5)页面生成者

PageConfigController
//页面静态化接口
    @PostMapping("/staticPage")
    AjaxResult staticPage(@RequestBody Map<String, String> map){
        String dataKey = map.get("dataKey");
        String pageName = map.get("pageName");
        try {
            pageConfigService.staticPage(dataKey,pageName);
            return AjaxResult.me();
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setSuccess(false).setMessage("静态化失败!"+e.getMessage());
        }

    }
@Override
    public void staticPage(String dataKey, String pageName) {
        FileOutputStream os = null;
        InputStream is = null;
        try {
            //一 页面静态化
            Pager pager = pagerMapper
                    .selectList(new EntityWrapper<Pager>().eq("name", pageName)).get(0);
            String templateUrl = pager.getTemplateUrl(); //fastdfs地址 zip包的
            String templateName = pager.getTemplateName(); //要执行模板文件

            //1.1 下载fastdfs上面压缩包
            Response response =
                    fastDfsClient.download(templateUrl); //通过fastdfs下载压缩包
            is = response.body().asInputStream();

            //1.2 所有静态化中间数据都写入临时目录
            //1)跨操作系统
            //2 操作系统会自动维护,不用删除
            String tmpdir=System.getProperty("java.io.tmpdir");
            System.out.println(tmpdir+"jjjjj.........");
            String zipPath = tmpdir+"/temp.zip"; //要下载zip包路径
            String unZipPath = tmpdir + "/temp/"; //解压到路径
            os = new FileOutputStream(zipPath);
            IOUtils.copy(is , os); //保存到本地

            ZipUtil.unzip(zipPath,unZipPath); // 解压缩

            //1.3 获取到模板
            String templatePath = unZipPath+"/"+templateName; //模板路径 temp/home.vm
            System.out.println(templatePath+"zz.........");
            //2 生成静态页面的路劲
            String templatePagePath = templatePath+".html"; //本地静态页面地址
            System.out.println(templatePagePath+"xxx.........");



            //3 生成数据
            String courseTypes =redisClient.get("courseTypes"); //redis数据
            List<CourseTypeDto> courseTypeDtos = JSONArray.parseArray(courseTypes,CourseTypeDto.class);
            Map<String, Object> modelMap = new HashMap<>(); //封装两个参数作为一个对象传入进去
            modelMap.put("staticRoot", unZipPath);
            modelMap.put("courseTypes", courseTypeDtos);


            //4 做页面静态化
            VelocityUtils.staticByTemplate(modelMap,templatePath,templatePagePath); //进行页面静态化

            // 5 传递到fastdfs
            String pageUrl = fastDfsClient.upload(
                    new CommonsMultipartFile(createFileItem(new File(templatePagePath),"file")));
            //二 PageConfig 并且进行保存
            PageConfig config = new PageConfig();
            config.setTemplateUrl(templateUrl);
            config.setTemplateName(templateName);
            config.setDataKey(dataKey);
            config.setPhysicalPath(pager.getPhysicalPath());
            config.setDfsType(0L); //0表示fastDfs
            config.setPageUrl(pageUrl);
            config.setPageId(pager.getId());
            pageConfigMapper.insert(config);
            //三 往消息队列放入消息
            String routingKey = siteMapper
                    .selectList(new EntityWrapper<Site>().eq("id", pager.getSiteId())).get(0).getSn();
            System.out.println(routingKey+"ddh......");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("fileSysType",0);
            jsonObject.put("staticPageUrl",pageUrl);
            jsonObject.put("physicalPath",pager.getPhysicalPath());
            System.out.println(jsonObject.toJSONString()+"dbl.....");
            rabbitTemplate.convertAndSend(
                    RabbitmqConstants.EXCHANGE_DIRECT_INFORM,routingKey,jsonObject.toJSONString());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /*
创建FileItem
 */
    private FileItem createFileItem(File file,String filedName) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem(filedName, "text/plain", true, file.getName());
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return item;
    }

(6)页面发布消费方

package cn.itsource.hrm.config;


import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 主站
 * 课程管理
 * 职位管理
 */
@Configuration
public class RabbitmqConfig {

    @Value("${rabbitmq.queues.routingKey}")
    public  String routingKey;
    public static final String EXCHANGE_DIRECT_INFORM = RabbitmqConstants.EXCHANGE_DIRECT_INFORM;
    public static final String QUEUE_INFORM_PAGESTATIC = RabbitmqConstants.QUEUE_INFORM_PAGESTATIC;

    /**
     * 交换机配置
     * ExchangeBuilder提供了fanout、direct、topic、header交换机类型的配置
     *
     * @return the exchange
     */
    @Bean(EXCHANGE_DIRECT_INFORM)
    public Exchange exchange_direct_inform() {
    //durable(true)持久化,消息队列重启后交换机仍然存在
        return ExchangeBuilder.directExchange(EXCHANGE_DIRECT_INFORM).durable(true).build();
    }

    //声明队列
    @Bean(QUEUE_INFORM_PAGESTATIC) //交给spring管理的bean的名字可以随便的
    public Queue pageStaticQueue() {
        Queue queue = new Queue(QUEUE_INFORM_PAGESTATIC); //队列名
        return queue;
    }

    //    Qualifier//获取特定名称bean
    @Bean
    public Binding BINDING_QUEUE_INFORM_HRMJOBSITE(@Qualifier(QUEUE_INFORM_PAGESTATIC) Queue queue,
                                              @Qualifier(EXCHANGE_DIRECT_INFORM) Exchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(routingKey).noargs();
    }


    public String getRoutingKey() {
        return routingKey;
    }

    public void setRoutingKey(String routingKey) {
        this.routingKey = routingKey;
    }
}

@Component
public class StaticPageDownloadHandler {

    @Autowired
    private FastDfsClient fastDfsClient;

    @RabbitListener(queues = RabbitmqConstants.QUEUE_INFORM_PAGESTATIC)
    public void receiveHomeSite(String msg, Message message, Channel channel) {
        //msg -fileSysType,staticPageUrl,physicalPath
        JSONObject jsonObject = JSONObject.parseObject(msg);
        Integer fileSysType = jsonObject.getInteger("fileSysType");
        String staticPageUrl = jsonObject.getString("staticPageUrl");
        String physicalPath = jsonObject.getString("physicalPath");
        System.out.println(staticPageUrl);
        System.out.println(physicalPath);

        switch (fileSysType) {
            case 0: //fastdfs
                fastDfsDownloadAndCopy(staticPageUrl, physicalPath);
                break;
            case 1: //hdfs
                hdfsDownloadAndCopy(staticPageUrl, physicalPath);
                break;
            default:
                break;
        }
    }
    /**
     * 通过fastdfs下载文件,并且拷贝到特定的目录
     * @param staticPageUrl
     * @param physicalPath
     */
    private void hdfsDownloadAndCopy(String staticPageUrl, String physicalPath) {

        //@TODO
    }

    /**
     * 通过fastdfs下载文件,并且拷贝到特定的目录
     * @param staticPageUrl
     * @param physicalPath
     */
    private void fastDfsDownloadAndCopy(String staticPageUrl, String physicalPath) {
        Response response = fastDfsClient.download(staticPageUrl);
        InputStream is = null;
        OutputStream os = null;
        try {
            is  = response.body().asInputStream();
            os = new FileOutputStream(physicalPath);
            IOUtils.copy(is,os);
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值