目前流行的三大页面视图神器是:老牌大哥jsp、后起之秀freemarker和velocity。这里不详细比较这三者的优劣,总体来说,jsp是标配,但后面两个更严格的执行了视图与业务的分离,页面里是不允许出现java代码的。velocity是模板语言,更强调复用,性能也更好一些,velocity就是速度的意思。freemarker的集成看spring mvc集成freemarker使用。
目前流行的web框架是spring mvc,作为整合老手spring可以无缝接洽上面三个视图解析器。这里着重看下velocity怎么在spring mvc里用。
首先定义spring的web配置文件:
spring-mvc.xm
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <context:component-scan base-package="com.wulinfeng.test.testpilling" /> <mvc:annotation-driven /> <!-- velocity配置 --> <bean id="velocityConfiger" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer"> <property name="resourceLoaderPath" value="/" /> <property name="configLocation" value="classpath:velocity.properties" /> </bean> <!-- 配置视图的显示 --> <bean id="ViewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"> <property name="cache" value="true" /> <property name="prefix" value="/" /><!-- 视图文件的前缀,即存放的路径 --> <property name="suffix" value=".html" /><!-- 视图文件的后缀名 --> <property name="dateToolAttribute" value="date" /><!--日期函数名称--> <property name="numberToolAttribute" value="number" /><!--数字函数名称--> <property name="contentType" value="text/html;charset=UTF-8" /> <property name="exposeSpringMacroHelpers" value="true" /><!--是否使用spring对宏定义的支持--> <property name="exposeRequestAttributes" value="true" /><!--是否开放request属性--> <property name="requestContextAttribute" value="rc"/><!--request属性引用名称--> </bean> </beans>
velocity.properties
#encoding
input.encoding=UTF-8
output.encoding=UTF-8
contentType=text/html;charset=UTF-8
#autoreload when vm changed
file.resource.loader.cache=false
file.resource.loader.modificationCheckInterval=1
velocimacro.library.autoreload=false
配置好了视图解析器后,我们来看下怎么在页面中用,分别列出controller和页面:
package com.wulinfeng.test.testpilling.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.wulinfeng.test.testpilling.service.TestPillingService; import com.wulinfeng.test.testpilling.util.PropertiesConfigUtil; @Controller public class TestPillingController { /** 主页 */ private static final String HOME_PAGE = PropertiesConfigUtil.getProperty("homepage"); @Autowired private TestPillingService testPillingService; /** * 加载主页 * * @author wulinfeng * @param model * @return */ @RequestMapping(value = "/home.html", method = RequestMethod.GET) public String getMethodContent(Model model) { testPillingService.initialize(model); return HOME_PAGE; } /** * 获取单个测试桩接口内容 * * @author wulinfeng * @param method * @return */ @RequestMapping(value = "/getMethod/{method}", method = RequestMethod.GET) public @ResponseBody String getMethodContent(@PathVariable("method") String method) { return testPillingService.getMethodContent(method); } /** * 新增测试桩 * * @author wulinfeng * @param method * @param requestBody * @return */ @RequestMapping(value = "/editMethod/{method}", method = RequestMethod.POST) public @ResponseBody void editMethodContent(@PathVariable("method") String method, @RequestBody String requestBody) { testPillingService.editMethodContent(method, requestBody); } /** * 删除测试桩 * * @author wulinfeng * @param method */ @RequestMapping(value = "/deleteMethod/{method}", method = RequestMethod.GET) public @ResponseBody void deleteMethodContent(@PathVariable("method") String method) { testPillingService.deleteMethodContent(method); } }
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试桩配置页面</title> </head> <body> <form id="interfaceForm"> <h2 align="center"> <font color="#FF0000">测试桩配置</font> </h2> <table style="width: 1200px; height: 600px; margin-left: 5%; margin-top: 30px;" border="2px" bordercolor="gray" cellspacing="0px" cellpadding="5px"> <tr height="10%"> <td rowspan="3" width="32%" valign="top" align="center"><font size="4pt" color="black">接口名称:</font><br /> <br /> <div name="interfaceNames" id="interfaceNames" style="border: solid 2px pink; width: 350px; height: 520px; overflow: auto;"> <table> #foreach($method in $methodKeys) <tr valign="top" style="height: 25px;"> <td align="center" width="150px"><a onclick="getMethodContent('$method');">$method</a></td> <td width="100px" align="left"><a style="text-decoration: none;" onclick="deleteInterfaceEntity('$method');"> 删除</a></td> </tr> #end </table> </div></td> <td>接口名: <input type="text" name="interfaceName" id="interfaceName" style="width: 400px" /> <input type="button" value="新增/修改" onclick="generateInterfaceEntity();" /></td> </tr> <tr> <td><font size="4pt" color="black"> 接口报文:</font><br /> <br /> <textarea name="interfaceBody" id="interfaceBody" style="width: 700px; height: 450px; margin-left: 50px;"> </textarea></td> </tr> </table> </form> </body> <script type="text/javascript"> var xmlHttp; //创建一个xmlHttpRequest对象 window.onload = function createxmlHttp() { try { //尝试创建 xmlHttpRequest 对象,除 IE 外的浏览器都支持这个方法。 xmlHttp = new XMLHttpRequest(); } catch (e) { try { //使用较新版本的 IE 创建 IE 兼容的对象(Msxml2.xmlHttp)。 xmlHttp = ActiveXObject("Msxml12.XMLHTTP"); } catch (e1) { try { //使用较老版本的 IE 创建 IE 兼容的对象(Microsoft.xmlHttp)。 xmlHttp = ActiveXObject("Microsoft.XMLHTTP"); } catch (e2) { flag = false; } } } //判断是否成功的例子: if (!xmlHttp) { alert("creat XMLHttpRequest Object failed."); } } //调用http接口获取接口内容 function getMethodContent(method) { url = "/getMethod/" + method; xmlHttp.open("GET", url, true); xmlHttp.onreadystatechange = showContent; document.getElementById("interfaceName").value = method; //将接口名放入html指定div中 xmlHttp.send(); } //回调函数,显示http响应结果 function showContent() { if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { var text = xmlHttp.responseText; //这里获得服务器返回的数据 document.getElementById("interfaceBody").innerHTML = text; //将数据放入html指定div中 } else { alert("response error code:" + xmlHttp.status); } } } //删除接口 function deleteInterfaceEntity(method) { url = "/deleteMethod/" + method; xmlHttp.open("GET", url, true); xmlHttp.onreadystatechange = showActionResult; xmlHttp.send(); } //新增、编辑接口 function generateInterfaceEntity() { url = "/editMethod/" + document.getElementById("interfaceName").value; xmlHttp.open("POST", url, true); xmlHttp.setRequestHeader("Content-type", "application/json;charset=UTF-8"); xmlHttp.onreadystatechange = showActionResult; xmlHttp.send(document.getElementById("interfaceBody").innerHTML); } //回调函数,显示action操作结果,刷新页面 function showActionResult() { if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { alert("operation success!"); window.location.reload(); } else { alert("operation failed! response error code:" + xmlHttp.status); } } } </script> </html>
下面是service类设置数据的方法
/** * 加载测试桩接口列表 * * @author wulinfeng * @param model */ public void initialize(Model model) { model.addAttribute("methodKeys", methodMap.keySet()); }
这里页面虽然是html,实际上就是velocity,注意看上面的配置<property name="suffix" value=".html" />,最后maven的pom文件里注意jar引入:
<dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-tools</artifactId> <version>2.0</version> <scope>compile</scope> </dependency>