Freemarker商品详情页静态化服务调用处理

来源:互联网 发布:java开发校招笔试题 编辑:程序博客网 时间:2024/05/18 22:54

最近在做一个移动电子商城的项目,在商品详情页处理这里处理的时候,因为我项目基本上都是用的jsp来写的页面,但是对于一个大型的购物网站来说,要解决掉速度的问题,所以需要把jsp换成html,这里我们可以使用Freemarker模板引擎来把jsp换成html供用户来访问.本文主要介绍的是如何使用Freemarker模板引擎来构建商品详情页,以及使用 CXF 做 webservice 发布服务,供后台添加商品时自动发布html网页。使用的是maven+SSM框架


一、FreeMarker

FreeMarker模板文件主要由如下4个部分组成:

1,文本:直接输出的部分 
2,注释:<#-- ... -->格式部分,不会输出 
3,插值:即${...}或#{...}格式的部分,将使用数据模型中的部分替代输出 
4,FTL指令:FreeMarker指定,和HTML标记类似,名字前加#予以区分,不会输出


关于FreeMarker的语法使用等这里不再重复说明,有需要的朋友可以自行查阅相关资料。


步骤:1,在core项目的resource文件下新建:productDetail.ftl文件,放在cn.tf.ecps.ftl目录下。

关键代码内容如下:就是通过FreeMarker的语法进行取值。

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:12px;"><div class="r wr">  
  2.         <div class="product">  
  3.             <h2>${item.itemName }<span class="gray f14">${item.promotion }</span></h2>  
  4.             <div class="showPro">  
  5.                 <div class="big"><a id="showImg" class="cloud-zoom" href="${file_path }${item.imgs}" rel="adjustX:10,adjustY:-1"><img title="optional title display" alt="" src="${file_path }${item.imgs}"></a></div>  
  6.                 <div class="small">  
  7.                     <span class="smallL" title="向左"> </span>  
  8.                     <div class="smallBox">  
  9.                         <div class="smallList">  
  10.                             <a class="cloud-zoom-gallery here" title="red" href="${file_path }${item.imgs}" rel="useZoom: 'showImg', smallImage: '${file_path }${item.imgs}'"><img alt="thumbnail 1" src="${file_path }${item.imgs}"></a>  
  11.                             <a class="cloud-zoom-gallery" title="blue" href="${file_path }${item.imgs}" rel="useZoom: 'showImg', smallImage: '${file_path }${item.imgs}'"><img alt="thumbnail 2" src="${file_path }${item.imgs}"></a>  
  12.                             <a class="cloud-zoom-gallery" title="blue" href="${file_path }${item.imgs}" rel="useZoom: 'showImg', smallImage: '${file_path }${item.imgs}'"><img alt="thumbnail 3" src="${file_path }${item.imgs}"></a>  
  13.                             <a class="cloud-zoom-gallery" title="blue" href="${file_path }${item.imgs}" rel="useZoom: 'showImg', smallImage: '${file_path }${item.imgs}'"><img alt="thumbnail 4" src="${file_path }${item.imgs}"></a>  
  14.                             <a class="cloud-zoom-gallery" title="blue" href="${file_path }${item.imgs}" rel="useZoom: 'showImg', smallImage: '${file_path }${item.imgs}'"><img alt="thumbnail 5" src="${file_path }${item.imgs}"></a>  
  15.                         </div>  
  16.                     </div>  
  17.                     <span class="smallR" title="向右"> </span>  
  18.                 </div>  
  19.                 <div class="share mt">  
  20.       
  21.                     <div id="ecpsShareIcon">  
  22.                         <div class="iconSmall iconRight">  
  23.                             <span>分享到:</span><a href="javascript:void(0);" target="_blank" class="sinawb" title="分享到新浪微博"></a><a href="javascript:void(0);" target="_blank" class="qqwb" title="分享到腾讯微博"></a><a href="javascript:void(0);" target="_blank" class="renren" title="分享到人人网"></a><a href="javascript:void(0);" target="_blank" class="qqzone" title="分享到QQ空间"></a><a href="javascript:void(0);" target="_blank" class="sohuwb" title="分享到搜狐微博"></a><a href="javascript:void(0);" class="copy" title="复制链接">复制链接</a>  
  24.                         </div>  
  25.                     </div>  
  26.                 </div>  
  27.             </div>  
  28.   
  29.             <form method="post" action="" name="" class="infor">  
  30.                 <ul class="uls form">  
  31.                   
  32.                 <li><label>移 动 价:</label><span class="word"><b id="skuPrice" class="f14 red mr">¥3999.00</b>(市场价:<del id="marketPrice">¥5789.00</del>)</span></li>  
  33.                 <li><label>商品编号:</label><span class="word">${item.itemNo }</span></li>  
  34.                 <li><label>商品评价:</label><span class="word"><span class="val_no val3d4" title="4分">4分</span><var class="blue">(已有17人评价)</var></span></li>  
  35.                 <li><label>运  费:</label><span class="word">包邮    <a href="javascript:void(0);" class="blue">配送区域</a></span></li>  
  36.                 <li><label>库  存:</label><span id="stockState" class="word">有货</span></li>  
  37.                 <li><label>支付方式:</label><div class="pre word p16x16">  
  38.                     <span title="网银支付" class="bank">网银支付</span>  
  39.                     <span title="支付宝" class="pay">支付宝</span>  
  40.                     <span title="手机支付" class="moblie">手机支付</span>  
  41.                 </div></li>  
  42.                 </ul>  
  43.                 <div class="box_orange">  
  44.                     <ul class="uls form">  
  45.                     <li><label>规  格:</label><div class="pre spec">  
  46.                     <#list item.skuList as sku>  
  47.                             <#if sku_index == 0>  
  48.                                 <a href="javascript:void(0);"  class="here" skuId="${sku.skuId?c }">  
  49.                                     <#list sku.specList as spec>  
  50.                                         ${spec.specValue }  
  51.                                     </#list>                        
  52.                                 </a>  
  53.                             <#else>  
  54.                                 <a href="javascript:void(0);" skuId="${sku.skuId?c }">  
  55.                                     <#list sku.specList as spec>  
  56. </span><pre code_snippet_id="1982693" snippet_file_name="blog_20161113_1_961446"><span style="font-size:12px;">                                     ${spec.specValue }  
  57. </span><span style="font-size:12px;">                                   </#list>                        
  58. </span><span style="font-size:12px;">                               </a>  
  59. </span><span style="font-size:12px;">                           </#if></span><span style="font-size:12px;">  
  60. </span><span style="font-size:12px;">                   </#list>    
  61. </span><span style="font-size:12px;">                   </div></li></span></pre><span style="font-size:12px;">                  <li><label>我 要 买:</label><a href="javascript:void(0);" class="inb sub"></a><input readonly type="text" name="" value="1" class="num" size="3" /><a href="javascript:void(0);" class="inb add"></a><em id="sub_add_msg" class="red"></em></li><li class="submit"><input id="buyNow" type="button" value="" class="hand btn138x40" onclick="buy();"/><input id="addMyCart" type="button" value="" class="hand btn138x40b" onclick="addCart()"/><a href="#" title="加入收藏" class="inb fav">加入收藏</a></li></ul></div></form></div></span><span style="font-size: 14px;"></span>  

2、FMUtils文件

在/src/main/Java/目录中新建一个util文件,这是用来处理的一个工具类。

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. public class FMutil {  
  2.       
  3.     /** 
  4.      *  
  5.      * @param ftlName:模板名字 
  6.      * @param fileName:生成的html的名字 
  7.      * @param map:数据,在freemarket模板中取数据都使用map 
  8.      * @throws Exception 
  9.      */  
  10.     public void ouputFile(String ftlName, String fileName,  Map<String, Object> map) throws Exception{  
  11.         //创建fm的配置  
  12.         Configuration config = new Configuration();  
  13.         //指定默认编码格式  
  14.         config.setDefaultEncoding("UTF-8");  
  15.         //设置模板的包路径  
  16.         config.setClassForTemplateLoading(this.getClass(), "/cn/tf/ecps/ftl");  
  17.         //获得包的模板  
  18.         Template template = config.getTemplate(ftlName);  
  19.         //指定文件输出的路径  
  20.         String path = "E:/myeclipse_work/ECPS/ecps-parent/ecps-portal/src/main/webapp/html";  
  21.         //定义输出流,注意的必须指定编码  
  22.         Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(path+"/"+fileName)),"UTF-8"));  
  23.         //生成模板  
  24.         template.process(map, writer);  
  25.     }  
  26. }  

3、测试

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. @Autowired  
  2.     private EbItemService itemService;  
  3.   
  4.     @Test  
  5.     public void testGeneraHtml() throws Exception {  
  6.         Map<String,Object>  map=new HashMap<String,Object> ();  
  7.         EbItem item=itemService.selectItemDetailById(3080);  
  8.         map.put("item", item);  
  9.           
  10.         map.put("path", ECPSUtil.readProp("portal_path"));  
  11.         map.put("file_path", ECPSUtil.readProp("FILE_PATH"));  
  12.         FMutil fm=new FMutil();  
  13.   
  14.          fm.ouputFile("productDetail.ftl", item.getItemId()+".html", map);  
  15.       
  16.     }  
  17.       

这个时候我们就可以看到页面效果出来了,在我们设置好的html目录下:就可以找到生成的html文件3080.html了




当然,在这里提一句的是,这个项目非常复杂,我只是简要的介绍一下使用FreeMarker的流程,而不是要介绍怎么做这个详情页最小单元的处理。

二、CXF服务调用

我们在做完这个模板处理之后,记u需要后台通过添加商品之后就可以将这个页面生成出来,例如我后台有10万个商品,那么我就需要生成10万个静态的html页面保存在我的html文件服务器上面。

例如我这个后台,点击发布按钮之后,就可以自动生成一个html文件,把商品下相关信息保存在那个html中,每次更新商品时重新点击发布就可以了,非常方便。



那么我们想要点击发布按钮之后就要生成代码,自然需要我们的FreeMarker了,在真实生产环境中,都是分布式的,不在同一台机器上面,所以这就涉及到了我们的webService调用了。这里使用的是appach的cxf来处理。

下载地址:http://cxf.apache.org/download.html


1、新建一个ws的接口类:EbWSItemService,这里的接口我使用了md5加密加盐处理。

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. @WebService  
  2. public interface EbWSItemService {  
  3.       
  4.     public String publishItem(Long itemId,String password);  
  5.   
  6. }  

实现其方法

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. @Service  
  2. public class EbWSItemServiceImpl  implements EbWSItemService {  
  3.   
  4.     @Autowired  
  5.     private EbItemService itemService;  
  6.       
  7.       
  8.     public String publishItem(Long itemId, String password) {  
  9.         String isOK="success";  
  10.           
  11.         String wsPass=GetMD5.getMD5(itemId);  
  12.         if(StringUtils.equals(password, wsPass)){  
  13.             //发布  
  14.             Map<String,Object>  map=new HashMap<String,Object> ();  
  15.             EbItem item=itemService.selectItemDetailById(itemId);  
  16.             map.put("item", item);  
  17.               
  18.             map.put("path", ECPSUtil.readProp("portal_path"));  
  19.             map.put("file_path", ECPSUtil.readProp("FILE_PATH"));  
  20.             FMutil fm=new FMutil();  
  21.             try {  
  22.                 fm.ouputFile("productDetail.ftl", item.getItemId()+".html", map);  
  23.             } catch (Exception e) {  
  24.                 e.printStackTrace();  
  25.             }  
  26.         }else{  
  27.             isOK="fail";  
  28.         }  
  29.           
  30.         return isOK;  
  31.     }  
  32. }  


属性文件内容为:ecps.properties

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. FILE_PATH=http://localhost:8080/ecps-file  
  2.   
  3. #操作类型  
  4. AUDIT_ITEM_TYPE=\u5546\u54C1\u5BA1\u6838  
  5. show_item_type=\u5546\u54C1\u4E0A\u4E0B\u67B6  
  6.   
  7. portal_path=http://localhost:8080/ecps-portal  
  8.   
  9. #接口加密  
  10. slat=xvzbnxsd^&&*)(*()kfmv4165323DGHSBJ  




2、在项目中新建一个文件cxf-servlet.xml

内容如下:

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"  
  4.     xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans   
  6.           http://www.springframework.org/schema/beans/spring-beans.xsd  
  7.             http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd  
  8.             http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd  
  9.             http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">  
  10.     <!-- 引入CXF Bean定义如下,早期的版本中使用 -->  
  11.     <import resource="classpath:META-INF/cxf/cxf.xml" />  
  12.     <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />  
  13.     <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  
  14.     <!--   
  15.         webservice服务地址:http://localhost:8080/ecps-portal/[url-patten]/address  
  16.         serviceClass:服务接口类  
  17.         jaxws:serviceBean:服务接口的实现类  
  18.           
  19.      -->  
  20.     <jaxws:server id="publishItem" address="/publishItem" serviceClass="cn.tf.ecps.ws.service.EbWSItemService">  
  21.         <jaxws:serviceBean>  
  22.             <bean class="cn.tf.ecps.ws.service.impl.EbWSItemServiceImpl"></bean>  
  23.         </jaxws:serviceBean>  
  24.     </jaxws:server>  
  25.       
  26. </beans>  

3、在前台工程的web.xml中进行配置

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <servlet>  
  2.         <servlet-name>cxf</servlet-name>  
  3.         <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>  
  4.     </servlet>  
  5.     <servlet-mapping>  
  6.         <servlet-name>cxf</servlet-name>  
  7.         <url-pattern>/services/*</url-pattern>  
  8.     </servlet-mapping>  


4、运行tomcat,通过链接访问:



里面就是一个wsdl文件。我们都知道wsdl都是从下往上读的,所以这里需要调用EbWSItemServiceService



发布服务之后我们需要使用这个cxf来生成java代码:

wsdl2java -d . -p cn.tf.ecps.stub http://localhost:8080/ecps-portal/services/publishItem?wsdl


生成好之后,将生成好的代码复制进你的工程即可。


然后在我们的port工程中,对service进行处理:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. //调用服务  
  2.     public String publishItem(Long itemId, String password) {  
  3.         //创建服务访问点的集合  
  4.         EbWSItemServiceService  itemServiceService=new EbWSItemServiceService();  
  5.         //获得服务端的接口,通过服务访问点的name在前面加上get这个方法就是获得webService服务的接口方法  
  6.         EbWSItemService service = itemServiceService.getEbWSItemServicePort();  
  7.         //调用webService的发布方法  
  8.         return service.publishItem(itemId, password);  
  9.     }  

最后在controller中调用那个这个service就可以了

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. //调用服务  
  2.     @RequestMapping("/publish.do")  
  3.     public void publish(Long itemId,PrintWriter out){  
  4.         String wsPass=GetMD5.getMD5(itemId);  
  5.         String result = null;  
  6.         try {  
  7.             result = itemService.publishItem(itemId,wsPass);  
  8.         } catch (Exception e) {  
  9.             e.printStackTrace();  
  10.         }  
  11.         out.write(result);  
  12.       
  13.     }  

这样整个过程就完成了。



这里值得一提的是如果你发布的服务是用的localhost:8080,那么在前台工程也要用localhost:8080,否则会报错,我就是因为这个原因折腾了几个小时,原因是跨域问题。

可以通过前台来看到生成好的html页面。

0 0
原创粉丝点击