`

Struts2结合Velocity开发(Layout布局方式)

阅读更多

Struts2结合Velocity开发(Layout布局方式)

 

1.重写Struts2中的VelocityResult,使其带有Layout功能

(原因:struts2默认只有不带布局功能的velocity模板类VelocityResult,所以需要重写)

package com.tairan.taihang.struts.velocity;

import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;

import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspFactory;
import javax.servlet.jsp.PageContext;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.VelocityResult;
import org.apache.struts2.views.JspSupportServlet;
import org.apache.struts2.views.velocity.VelocityManager;
import org.apache.velocity.Template;
import org.apache.velocity.context.Context;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;

public class VelocityLayoutResult extends VelocityResult {

private static final long serialVersionUID = 6020934292083047099L;

private static final Logger LOG = LoggerFactory.getLogger(VelocityLayoutResult.class);

public static String KEY_SCREEN_CONTENT = "screen_content";
public static String KEY_LAYOUT = "layout";
public static final String PROPERTY_DEFAULT_LAYOUT = "tools.view.servlet.layout.default.template";
public static final String PROPERTY_LAYOUT_DIR = "tools.view.servlet.layout.directory";
public static final String PROPERTY_INPUT_ENCODING = "input.encoding";
public static final String PROPERTY_OUTPUT_ENCODING = "output.encoding";
public static final String PROPERTY_CONTENT_TYPE = "default.contentType";

protected VelocityManager velocityManager;
protected String defaultLayout;
protected String layoutDir;
protected String inputEncoding;
protected String outputEncoding;
protected String contentType;

@Override
public void setVelocityManager(VelocityManager mgr) {
   this.velocityManager = mgr;
   super.setVelocityManager(mgr);
}

@Override
public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
   ValueStack stack = ActionContext.getContext().getValueStack();

   HttpServletRequest request = ServletActionContext.getRequest();
   HttpServletResponse response = ServletActionContext.getResponse();
   JspFactory jspFactory = null;
   ServletContext servletContext = ServletActionContext.getServletContext();
   Servlet servlet = JspSupportServlet.jspSupportServlet;

   velocityManager.init(servletContext);

   boolean usedJspFactory = false;
   PageContext pageContext = (PageContext) ActionContext.getContext().get(ServletActionContext.PAGE_CONTEXT);

   if (pageContext == null && servlet != null) {
    jspFactory = JspFactory.getDefaultFactory();
    pageContext = jspFactory.getPageContext(servlet, request, response, null, true, 8192, true);
    ActionContext.getContext().put(ServletActionContext.PAGE_CONTEXT, pageContext);
    usedJspFactory = true;
   }

   try {
    String encoding = getEncoding(finalLocation);

    String contentType = getContentType(finalLocation);

    if (encoding != null) {
     contentType = contentType + ";charset=" + encoding;
    }

    Template t = getTemplate(stack, velocityManager.getVelocityEngine(), invocation, finalLocation, encoding);

    Context context = createContext(velocityManager, stack, request, response, finalLocation);
    StringWriter stringWriter = new StringWriter();
    t.merge(context, stringWriter);
    context.put(KEY_SCREEN_CONTENT, stringWriter.toString());

    Object obj = context.get(KEY_LAYOUT);
    String layout = (obj == null) ? null : obj.toString();

    defaultLayout = (String) velocityManager.getVelocityEngine().getProperty(PROPERTY_DEFAULT_LAYOUT);
    layoutDir = (String) velocityManager.getVelocityEngine().getProperty(PROPERTY_LAYOUT_DIR);
    if (!layoutDir.endsWith("/")) {
     layoutDir += '/';
    }

    if (!layoutDir.startsWith("/")) {
     layoutDir = "/" + layoutDir;
    }

    defaultLayout = layoutDir + defaultLayout;

    if (layout == null) {
     layout = defaultLayout;
    } else {
     layout = layoutDir + layout;
    }

    Template layoutVm = null;
    try {
     inputEncoding = (String) velocityManager.getVelocityEngine().getProperty(PROPERTY_INPUT_ENCODING);
     layoutVm = getTemplate(stack, velocityManager.getVelocityEngine(), invocation, layout, inputEncoding);
    } catch (Exception e) {
     LOG.error("VelocityLayoutResult: Can't load layout \"" + layout + "\": " + e);

     if (!layout.equals(defaultLayout)) {
      layoutVm = getTemplate(stack, velocityManager.getVelocityEngine(), invocation, defaultLayout,
        inputEncoding);
     }
    }

    outputEncoding = (String) velocityManager.getVelocityEngine().getProperty(PROPERTY_OUTPUT_ENCODING);
    Writer writer = new OutputStreamWriter(response.getOutputStream(), outputEncoding);
    response.setContentType(contentType);

    layoutVm.merge(context, writer);
    writer.flush();
   } catch (Exception e) {
    LOG.error("Unable to render Velocity Template, '" + finalLocation + "'", e);
    throw e;
   } finally {
    if (usedJspFactory) {
     jspFactory.releasePageContext(pageContext);
    }
   }

   return;
}

}

 

2.在struts.xml中增加velocity相关配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <!-- struts.objectFactory这个属性用于说明Struts2的 对象池创建工厂当想要得到Spring中的对象池时, -->
    <!-- 申明struts.objectFactory为Spring的对象池构建工厂 -->
    <constant name="struts.objectFactory" value="spring" />
    <!-- 该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为false -->
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
    <!-- 该属性设置Struts 2应用是否使用开发模式。如果设置该属性为true,则可以在应用出错时显示更多、更友好的出错提示。 -->
    <!-- 通常,应用在开发阶段,将该属性设置为true,当进入产品发布阶段后,则该属性设置为false -->
    <constant name="struts.devMode" value="false" />
    <!-- 该属性设置是否每次HTTP请求到达时,系统都重新加载资源文件 , -->
    <!-- 该属性默认值是false。在开发阶段将该属性设置为true会更有利于开发,但在产品发布阶段应将该属性设置为false。 -->
    <constant name="struts.i18n.reload" value="false" />
    <!-- 该属性设置当struts.xml文件改变后,系统是否自动重新加载该文件。该属性的默认值是false -->
    <constant name="struts.configuration.xml.reload" value="false" />
    <!-- 该属性指定Struts 2应用所需要的国际化资源文件,如果有多份国际化资源文件,则多个资源文件的文件名以英文逗号(,)隔开 -->
    <constant name="struts.custom.i18n.resources" value="globalMessages,filePath" />
    <!-- 该属性指定Struts 2生成URL时是否包含请求参数。 -->
    <!-- 该属性接受none、get和all三个属性值,分别对应于不包含、仅包含GET类型请求参数和包含全部请求参数。 -->
    <!-- <constant name="struts.url.includeParams" value="none" /> -->
    <!-- 该属性指定视图标签默认的视图主题,该属性的默认值是xhtml -->
    <constant name="struts.ui.theme" value="simple" />
    <!-- 设置velocity配置文件 -->
    <constant name="struts.velocity.configfile" value="velocity.properties"/>
    <!-- 该属性设置文件上传的大小,现设置为10MB. -->
    <constant name="struts.multipart.maxSize" value="10485760" />
   
    
    <package name="user" extends="struts-default">
    
    	<result-types>
			<result-type name="velocity" class="com.tairan.taihang.struts.velocity.VelocityLayoutResult"/>
		</result-types>
		
		<interceptors>
			<!-- 自定义登录拦截器 -->
			<interceptor name="loginInterceptor" class="loginInterceptor"/>
			<!-- 异常拦截器 -->
			<!-- <interceptor name="exception" class="com.opensymphony.xwork.interceptor.ExceptionmappingInterceptor" /> -->
			<!-- 拦截器栈 -->
			<interceptor-stack name="myDefault">
				<interceptor-ref name="defaultStack" />		
				<interceptor-ref name="loginInterceptor" />	
				<!-- <interceptor-ref name="exception"></interceptor-ref> -->
			</interceptor-stack>				
		</interceptors>
		
		<global-results>
			<!-- 拦截器跳转到登录页面 -->
			<result name="toLogin" type="velocity">WEB-INF/vm/screen/storage/user/login.vm</result>
			<!-- 统一的错误页面 -->
			<result name="error" type="velocity">WEB-INF/vm/screen/storage/error.vm</result>
			<!-- 异常页面 -->
			<result name="root" type="velocity">WEB-INF/vm/screen/storage/error.vm</result>
			<result name="sql" type="velocity">WEB-INF/vm/screen/storage/error.vm</result>
		</global-results>
		
		<!-- 全局异常处理 -->
		<global-exception-mappings>
			<!-- Action抛出Exception时,转入名为root的结果 -->
			<exception-mapping result="root" exception="java.lang.Exception" />
			<!-- Action抛出SqlException时,转入名为sql的结果 -->
			<exception-mapping result="sql" exception="java.sql.Exception" />
		</global-exception-mappings>
		
		
        <action name="index" class="userAction" method="index">  
            <result name="success" type="velocity">WEB-INF/vm/screen/storage/index.vm</result>  
        </action>  
        
        <action name="toLogin" class="userAction" method="toLogin">
        	<result name="success" type="velocity">WEB-INF/vm/screen/storage/user/login.vm</result>
        </action>
        
        <action name="login" class="userAction" method="login">
        	<result name="success" type="redirectAction">userInfo</result>
        	<result name="input" type="velocity">WEB-INF/vm/screen/storage/user/login.vm</result>
        </action>
        
        <action name="toRegister" class="userAction" method="toRegister">
        	<result name="success" type="velocity">WEB-INF/vm/screen/storage/user/register.vm</result>
        </action>
        
        <action name="register" class="userAction" method="register">
        	<result name="success" type="velocity">WEB-INF/vm/screen/storage/user/registerSuccess.vm</result>
        	<result name="input" type="velocity">WEB-INF/vm/screen/storage/user/register.vm</result>
        </action>
        
        <action name="json" class="userAction" method="toJson">
        	<result name="success" type="velocity">WEB-INF/vm/screen/storage/jsonTest.vm</result>
        </action>
        
        <action name="exit" class="userAction" method="exit">
        	<result name="success" type="velocity">WEB-INF/vm/screen/storage/user/login.vm</result>
        </action>
        
    </package>
    
    <package name="userInfo" extends="user">
    
    	<action name="userInfo" class="userInfoAction" method="userInfo">
    		<interceptor-ref name="myDefault" />
    		<result name="success" type="velocity">WEB-INF/vm/screen/storage/userInfo/userInfo.vm</result>
    	</action>
    	
    	<action name="toAddUserInfo" class="userInfoAction" method="toAddUserInfo">
    		<interceptor-ref name="myDefault" />
    		<result name="success" type="velocity">WEB-INF/vm/screen/storage/userInfo/addUserInfo.vm</result>
    	</action>
    	
    	<action name="addUserInfo" class="userInfoAction" method="addUserInfo">
    		<result name="success" type="redirectAction">userInfo</result>
    	</action>
    	
    	<action name="toModifyUserInfo" class="userInfoAction" method="toModifyUserInfo">
    		<interceptor-ref name="myDefault" />
    		<result name="success" type="velocity">WEB-INF/vm/screen/storage/userInfo/modifyUserInfo.vm</result>
    	</action>

		<action name="modifyUserInfo" class="userInfoAction" method="modifyUserInfo">
    		<result name="success" type="redirectAction">userInfo</result>
    	</action>
    	
    	<action name="toDeleteUserInfo" class="userInfoAction" method="deleteUserInfo">
    		<interceptor-ref name="myDefault" />
    		<result name="success" type="redirectAction">userInfo</result>
    	</action>
		    
    </package>
    
    
    <!-- JSON -->
    <package name="jsonTest" extends="json-default">  
     	<action name="testList" class="jsonAction" method="getList">               
         	<result type="json">  
             	<param name="root">responseJsonList</param>  
         	</result>  
     	</action>  
     	<action name="testMap" class="jsonAction" method="getMap">               
         	<result type="json">  
             	<param name="root">responseJsonMap</param>  
         	</result>  
     	</action>  
     	<action name="testObject" class="jsonAction" method="getObject">               
         	<result type="json">  
             	<param name="root">responseJsonObject</param>  
         	</result>  
     	</action>  
     	<action name="checkName" class="userAction" method="checkName">
        	<result type="json">
        		<param name="root">errorMsg</param>
        	</result>
        </action>
        <action name="checkRegisterName" class="userAction" method="checkRegisterName">
        	<result type="json">
        		<param name="root">errorMsg</param>
        	</result>
        </action>
 	</package>  
    
</struts>

需要注意的地方有3点:

(1).设置velocity配置文件 

<constant name="struts.velocity.configfile" value="velocity.properties"/>

(2).修改struts2引用的VelocityResult类为我们重写后的类  

<result-types>
	result-type name="velocity" class="com.tairan.taihang.struts.velocity.VelocityLayoutResult"/>
</result-types>

(3).type不再是默认的dispatcher,修改为velocity

 

<result name="toLogin" type="velocity">WEB-INF/vm/screen/storage/user/login.vm</result>
 

 

 

 3.增加velocity相关配置文件:velocity.properties

 

tools.view.servlet.layout.directory =/WEB-INF/vm/layout/
tools.view.servlet.layout.default.template=default.vm
input.encoding=UTF-8
output.encoding=UTF-8
 

 

 

4.增加默认布局文件:default.vm

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>

	<meta http-equiv="Content-Type" content="IE=edge;text/html; charset=utf-8" />
	
	<link href="htdocs/sc/css/bootstrap.css" rel="stylesheet" type="text/css">
	<link href="htdocs/sc/css/bootstrap-progress.css" rel="stylesheet" media="screen">
	<link href="htdocs/sc/css/grumble.css" rel="stylesheet" media="screen">
	<link href="htdocs/sc/css/bootstrap-modal.css" rel="stylesheet"  media="screen">
	<link href="htdocs/sc/css/bootstrap-switch.css" rel="stylesheet" media="screen">
	<link href="htdocs/css/taihang.css" rel="stylesheet" type="text/css">
	<!--validform  -->
	<link href="htdocs/sc/css/style.css" rel="stylesheet" type="text/css">
	<!--jquery datepicker  -->
	<link href="htdocs/sc/css/jquery-ui.css" rel="stylesheet" type="text/css">
	
    <script src="htdocs/sc/js/jquery-1.8.3.js"></script>
    <script src="htdocs/sc/js/bootstrap.js"></script>
	<script src="htdocs/sc/js/bootstrap-switch.js"></script>
    <script src="htdocs/sc/js/grumble.min.js"></script>
    <script src="htdocs/sc/js/thtools.js"></script>
    <script src="htdocs/sc/js/Chart.js"></script>
 	<!--validform   -->
 	<script type="text/javascript" src="htdocs/sc/js/Validform_v5.3.2.js" ></script>
 	<script type="text/javascript" src="htdocs/sc/js/Validform_Datatype.js" ></script>
 	<script type="text/javascript" src="htdocs/sc/js/sc_Datatype.js" ></script>
	<!--jquery datepicker  --> 	
	<script type="text/javascript" src="htdocs/sc/js/jquery-ui-datepicker.js" ></script>
 	
 	    

</head>

<body>
	#if($pageIndex=='customersSub')
		$screen_content
	#elseif($pageIndex=='customersCenter')
		#parse('/WEB-INF/vm/control/head.vm')
		#parse('/WEB-INF/vm/control/centerTop.vm')
		<div class="div980 adjust pt10">
			#parse('/WEB-INF/vm/control/centerLeft.vm')
			$screen_content
        </div>
        #parse('/WEB-INF/vm/control/bottom.vm')
	#end

</body>
</html>
 

 

 

5.在vm页面代码中设置布局:

#set($pageIndex="customersCenter")

<div>
	<h1>欢迎光临!</h1>
</div>   

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics