ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

第7章:页面静态化-02-生成移动端静态页面

第7章:页面静态化-02-生成移动端静态页面 5. 生成移动端静态页面前面我们已经学习了Freemarker的基本使用方法下面我们就可以将Freemarker应用到项目中帮我们生成移动端套餐列表静态页面和套餐详情静态页面。接下来我们需要思考几个问题1什么时候生成静态页面比较合适呢2将静态页面生成到什么位置呢3应该生成几个静态页面呢对于第一个问题应该是当套餐数据发生改变时需要生成静态页面即我们通过后台系统修改套餐数据包括新增、删除、编辑时。对于第二个问题如果是在开发阶段可以将文件生成到项目工程中如果上线后可以将文件生成到移动端系统运行的tomcat中。对于第三个问题套餐列表只需要一个页面就可以了在这个页面中展示所有的套餐列表数据即可。套餐详情页面需要有多个即一个套餐应该对应一个静态页面。5.1 环境搭建在health_common工程的pom文件中导入Freemarker的maven坐标!--freemarker-- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-freemarker/artifactId /dependency5.2 创建模板文件在health_service_provider工程的templates目录中创建模板文件mobile_setmeal.ftl和mobile_setmeal_detail.ftl文件前者是用于生成套餐列表页面的模板文件后者是生成套餐详情页面的模板文件1mobile_setmeal.ftl!DOCTYPE html html langzh-CN head meta charsetutf-8 meta http-equivX-UA-Compatible contentIEedge !-- 上述3个meta标签*必须*放在最前面任何其他内容都*必须*跟随其后 -- meta nameviewport contentwidthdevice-width, initial-scale1.0, maximum-scale1.0, user-scalable0,user-scalableno,minimal-ui meta namedescription content meta nameauthor content link relicon href../img/asset-favico.ico title预约/title link relstylesheet href../css/page-health-order.css / /head body data-spyscroll data-target#myNavbar data-offset150 div classapp idapp !-- 页面头部 -- div classtop-header span classf-lefti classicon-back onclickhistory.go(-1)/i/span span classcenter健康管理系统/span span classf-righti classicon-more/i/span /div !-- 页面内容 -- div classcontentBox div classlist-column1 ul classlist #list setmealList as setmeal li classlist-item a classlink-page hrefsetmeal_detail_${setmeal.id}.html img classimg-object f-left srchttp://r9peo7bmf.hn-bkt.clouddn.com/${setmeal.img} alt div classitem-body h4 classellipsis item-title${setmeal.name}/h4 p classellipsis-more item-desc${setmeal.remark}/p p classitem-keywords span #if setmeal.sex 0 性别不限 #else #if setmeal.sex 1 男 #else 女 /#if /#if /span span${setmeal.age}/span /p /div /a /li /#list /ul /div /div /div !-- 页面 css js -- script src../plugins/vue/vue.js/script script src../plugins/vue/axios-0.18.0.js/script /body /html注意上面模板文件中每个套餐对应的超链接如下a classlink-page hrefsetmeal_detail_${setmeal.id}.html可以看到链接的地址是动态构成的如果套餐的id为1则对应的超链接地址为setmeal_detail_1.html如果套餐的id为5则对应的超链接地址为setmeal_detail_5.html。所以我们需要为每个套餐生成一个套餐详情静态页面。2mobile_setmeal_detail.ftl!DOCTYPE html html langzh-CN head meta charsetutf-8 meta http-equivX-UA-Compatible contentIEedge !-- 上述3个meta标签*必须*放在最前面任何其他内容都*必须*跟随其后 -- meta nameviewport contentwidthdevice-width, initial-scale1.0, maximum-scale1.0, user-scalable0,user-scalableno,minimal-ui meta namedescription content meta nameauthor content link relicon href../img/asset-favico.ico title预约详情/title link relstylesheet href../css/page-health-orderDetail.css / script src../plugins/vue/vue.js/script script src../plugins/vue/axios-0.18.0.js/script script src../plugins/healthmobile.js/script /head body data-spyscroll data-target#myNavbar data-offset150 div idapp classapp !-- 页面头部 -- div classtop-header span classf-lefti classicon-back onclickhistory.go(-1)/i/span span classcenter健康管理系统/span span classf-righti classicon-more/i/span /div !-- 页面内容 -- div classcontentBox div classcard div classproject-img img srchttp://r9peo7bmf.hn-bkt.clouddn.com/${setmeal.img} width100% height100% / /div div classproject-text h4 classtit${setmeal.name}/h4 p classsubtit${setmeal.remark}/p p classkeywords span #if setmeal.sex 0 性别不限 #else #if setmeal.sex 1 男 #else 女 /#if /#if /span span${setmeal.age}/span /p /div /div div classtable-listbox div classbox-title i classicon-zhenspan classpath1/spanspan classpath2/span/i span套餐详情/span /div div classbox-table div classtable-title div classtit-item flex2项目名称/div div classtit-item flex3项目内容/div div classtit-item flex3项目解读/div /div div classtable-content ul classtable-list #list setmeal.checkGroups as checkgroup li classtable-item div classitem flex2${checkgroup.name}/div div classitem flex3 #list checkgroup.checkItems as checkitem label ${checkitem.name} /label /#list /div div classitem flex3${checkgroup.remark}/div /li /#list /ul /div div classbox-button a clicktoOrderInfo() classorder-btn立即预约/a /div /div /div /div /div script var vue new Vue({ el:#app, methods:{ toOrderInfo(){ window.location.href orderInfo.html?id${setmeal.id}; } } }); /script /body /html5.3 配置文件1在health_service_provider工程application.yml 配置freemarkerspring: freemarker: # 模板后缀名 suffix: .ftl # 文档类型 content-type: text/html # 页面编码 charset: UTF-8 # 页面缓存 cache: false # 模板路径 template-loader-path: classpath:/templates/ #freemarker文件输出地址 out_put_path: D:/IdeaProjects9/health_parent/health_mobile/src/main/resources/static/pages通过上面的配置可以指定将静态HTML页面生成的目录位置5.4 生成静态页面修改health_service_provider工程中的SetmealServiceImpl类的add方法加入生成静态页面的逻辑。package com.liusp.service.impl; import com.alibaba.dubbo.config.annotation.Service; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.liusp.constant.RedisConstant; import com.liusp.dao.SetmealDao; import com.liusp.entity.PageResult; import com.liusp.pojo.Setmeal; import com.liusp.service.SetmealService; import freemarker.template.Configuration; import freemarker.template.Template; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; import java.io.*; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 体检套餐服务实现类 */ Service(interfaceClass SetmealService.class) Transactional public class SetmealServiceImpl implements SetmealService { Autowired private SetmealDao setmealDao; Autowired private RedisTemplate redisTemplate; Autowired private FreeMarkerConfigurer freeMarkerConfigurer; Value(${out_put_path})//从属性文件读取输出目录的路径 private String outputpath ; //新增套餐 public void add(Setmeal setmeal, Integer[] checkgroupIds) { setmealDao.add(setmeal); if(checkgroupIds ! null checkgroupIds.length 0){ //绑定套餐和检查组的多对多关系 setSetmealAndCheckGroup(setmeal.getId(),checkgroupIds); } //将图片名称保存到Redis savePic2Redis(setmeal.getImg()); //新增套餐后需要重新生成静态页面 generateMobileStaticHtml(); } //生成静态页面 public void generateMobileStaticHtml() { //准备模板文件中所需的数据 ListSetmeal setmealList this.findAll(); //生成套餐列表静态页面 generateMobileSetmealListHtml(setmealList); //生成套餐详情静态页面多个 generateMobileSetmealDetailHtml(setmealList); } //生成套餐列表静态页面 public void generateMobileSetmealListHtml(ListSetmeal setmealList) { MapString, Object dataMap new HashMapString, Object(); dataMap.put(setmealList, setmealList); this.generateHtml(mobile_setmeal.ftl,m_setmeal.html,dataMap); } //生成套餐详情静态页面多个 public void generateMobileSetmealDetailHtml(ListSetmeal setmealList) { for (Setmeal setmeal : setmealList) { MapString, Object dataMap new HashMapString, Object(); dataMap.put(setmeal, this.findById(setmeal.getId())); this.generateHtml(mobile_setmeal_detail.ftl, setmeal_detail_setmeal.getId().html, dataMap); } } public void generateHtml(String templateName,String htmlPageName,MapString, Object dataMap){ Configuration configuration freeMarkerConfigurer.getConfiguration(); Writer out null; try { // 加载模版文件 Template template configuration.getTemplate(templateName); // 生成数据 File docFile new File(outputpath \\ htmlPageName); out new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile))); // 输出文件 template.process(dataMap, out); } catch (Exception e) { e.printStackTrace(); } finally { try { if (null ! out) { out.flush(); } } catch (Exception e2) { e2.printStackTrace(); } } } //将图片名称保存到Redis private void savePic2Redis(String pic){ redisTemplate.opsForSet().add(RedisConstant.SETMEAL_PIC_DB_RESOURCES,pic); } //绑定套餐和检查组的多对多关系 private void setSetmealAndCheckGroup(Integer id, Integer[] checkgroupIds) { for (Integer checkgroupId : checkgroupIds) { MapString,Integer map new HashMap(); map.put(setmeal_id,id); map.put(checkgroup_id,checkgroupId); setmealDao.setSetmealAndCheckGroup(map); } } public PageResult pageQuery(Integer currentPage, Integer pageSize, String queryString) { PageHelper.startPage(currentPage,pageSize); PageSetmeal page setmealDao.selectByCondition(queryString); return new PageResult(page.getTotal(),page.getResult()); } public ListSetmeal findAll() { return setmealDao.findAll(); } public Setmeal findById(int id) { return setmealDao.findById(id); } }测试新增套餐查看生成的html页面。注意tomcat运行报Unable to process Jar entry [module-info.class] from Jar ...... jaxb-api-2.3.0.jar for annotations这个错误解决办法找到Maven仓库中的jaxb-api-2.3.0.jar包右击这个jar用压缩工具打开删除打开文件里的module-info.class文件夹删除的时候要停掉Tomcat服务否则无法删除。删除后重启服务。
返回列表