【前言】所謂快速開發(fā),實質(zhì)上為了節(jié)省項目的開支成本,減少程序員的開發(fā)時間,固然就形成了種種二次封裝的框架,也就是造輪子,然后我們的程序就按照這個輪子去畫瓢,這里我就把公司這幾次開發(fā)系統(tǒng)的框架源碼貼出來,做一下講解以及使用示范,并有附件提供參考,希望能給各位在基于后臺管理系統(tǒng)提供幫助。
解析:上面我對配置文件中加入(1)、(2)、(3)、(4),表示對此處的標注,下面我就對這些部分進行解析。
(1):如果有用過struts2的童鞋,可以清晰的看出它們名稱都很有含義,對沒錯 struts2的Action類已經(jīng)封裝這4個靜態(tài)常量,當我們在Action的方法中完成操作后,要對視圖進行 跳轉(zhuǎn)或者響應(yīng)時,要返回一個字符串,比如:return SUCCESS;那么這個SUCCESS實際上就是對應(yīng)我們在struts2配置的
(2) :很奇怪為什么有個${target},${target}只是作為struts2的配置的占位參數(shù),而基類BaseAction中我們存放了一個target變量,當解析struts.xml時,可以從我們實現(xiàn)類中讀 取出來,然后進行替換,這樣做的好處是什么,很顯然,我們要返回的jsp頁面有成千上萬種,我不可能每次都去配置
....,這樣可以說是實現(xiàn)了統(tǒng)一設(shè)置路徑,也就是通配,而且還有不同類型的返回,type="redirect"/ type="redirectAction",看上去好像是一樣的,區(qū)別在于redirectAction可以指定重定向到某個action上(struts2中配置的action),target就是Action的name,值得注意的是我這里只是羅列了重定向以及Jsp視圖的類型,要知道還有其他N多種類型的視圖,怎么辦?我先把關(guān)于模板類型的返回的告知出來以freemaker為例,其他見基類BaseAction:
比如:st.sys.web.UserAction.java - sttbas_server/src/java這樣一個類,我們訪問它的查詢方法:sys/User/view.action,很簡單。
好像struts.xml少了點什么東西,對我們沒有配置它的屬性,這里我們將struts2的屬性配置進行區(qū)分,也是官方推薦的設(shè)置將struts.xml,與struts.properties分開,并放入classpath目錄下,struts.properties內(nèi)容如下:
package com.st.web.action;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;
import com.st.utils.AjaxMsg;
import com.st.utils.JsonUtil;
/**
* @author fisher
* @description Action公共基類
* @param 所有對象類型
*/
public abstract class BaseAction extends ActionSupport implements
ModelDriven, Preparable, SessionAware, ServletRequestAware,
ServletResponseAware {
/**
*
*/
private static final long serialVersionUID = 1L;
protected Log log = LogFactory.getLog(getClass());
// -- header 常量定義 --//
private static final String HEADER_ENCODING = "encoding";
private static final String HEADER_NOCACHE = "no-cache";
private static final String DEFAULT_ENCODING = "UTF-8";
private static final boolean DEFAULT_NOCACHE = true;
// -- Content Type 定義 --//
public static final String TEXT_TYPE = "text/plain";
public static final String JSON_TYPE = "application/json";
public static final String XML_TYPE = "text/xml";
public static final String HTML_TYPE = "text/html";
public static final String JS_TYPE = "text/javascript";
public static final String EXCEL_TYPE = "application/vnd.ms-excel";
public static final String IMG_TYPE = "image/jpeg";
// -------------------- 作用域?qū)ο?--------------------//
/** sessionMap對象 */
private Map sessionMap;
/** request對象 */
private HttpServletRequest request;
/** response對象 */
private HttpServletResponse response;
/** ajax消息 */
public static final AjaxMsg ajaxMsg = new AjaxMsg();
// --------------------視圖跳轉(zhuǎn)路徑------------------//
/**
* 例如:"index.jsp index.ftl"
*/
private String target;
// -- Preparable函數(shù) --//
/**
* 實現(xiàn)空的prepare()函數(shù),屏蔽了所有Action函數(shù)都會執(zhí)行的公共的二次綁定.
*/
public void prepare() throws Exception {
}
// -------------繞過jsp/freemaker直接輸出文本函數(shù)-------------//
// -- 繞過jsp/freemaker直接輸出文本的函數(shù) --//
/**
* 直接輸出內(nèi)容的簡便函數(shù). eg. render("text/plain", "hello", "encoding:GBK");
* render("text/plain",hello", "no-cache:false");
* render("text/plain","hello", "encoding:GBK","no-cache:false");
*
* @param headers
* 可變的header數(shù)組,目前接受的值為"encoding:"或"no-cache:",默認值分別為UTF-8和true.
*/
public static void render(final String contentType, final String content,
final String... headers) {
HttpServletResponse response = initResponseHeader(contentType, headers);
try {
response.getWriter().write(content);
response.getWriter().flush();
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
public static void renderImg(final String img, final String... headers) {
render(IMG_TYPE, img, headers);
}
/**
* 直接輸出文本.
*
* @see #render(String, String, String...)
*/
public static void renderText(final String text, final String... headers) {
render(TEXT_TYPE, text, headers);
}
/**
* 直接輸出HTML.
*
* @see #render(String, String, String...)
*/
public static void renderHtml(final String html, final String... headers) {
render(HTML_TYPE, html, headers);
}
/**
* 直接輸出XML.
*
* @see #render(String, String, String...)
*/
public static void renderXml(final String xml, final String... headers) {
render(XML_TYPE, xml, headers);
}
/**
* 直接輸出JSON.
*
* @param jsonString
* json字符串.
* @see #render(String, String, String...)
*/
public static void renderJson(final String jsonString,
final String... headers) {
render(JSON_TYPE, jsonString, headers);
}
/**
* 直接輸出JSON,使用fastJson轉(zhuǎn)換Java對象.
*
* @param data
* 可以是List
, POJO[], POJO, 也可以Map名值對. * @see #render(String, String, String...)
*/
public static void renderJson(final Object data, final String... headers) {
String jsonString = JsonUtil.serialize(data);
renderJson(jsonString, headers);
}
public static void renderJson(final Object data,
final String[] propertyFilter, final boolean isInclude,
final String... headers) {
String jsonString = JsonUtil.serialize(data, propertyFilter, isInclude);
renderJson(jsonString, headers);
}
/**
* 分析并設(shè)置contentType與headers.
*/
private static HttpServletResponse initResponseHeader(
final String contentType, final String... headers) {
// 分析headers參數(shù)
String encoding = DEFAULT_ENCODING;
boolean noCache = DEFAULT_NOCACHE;
for (String header : headers) {
String headerName = StringUtils.substringBefore(header, ":");
String headerValue = StringUtils.substringAfter(header, ":");
if (StringUtils.equalsIgnoreCase(headerName, HEADER_ENCODING)) {
encoding = headerValue;
} else if (StringUtils.equalsIgnoreCase(headerName, HEADER_NOCACHE)) {
noCache = Boolean.parseBoolean(headerValue);
} else {
throw new IllegalArgumentException(headerName
+ "不是一個合法的header類型");
}
}
HttpServletResponse response = ServletActionContext.getResponse();
// 設(shè)置headers參數(shù)
String fullContentType = contentType + ";charset=" + encoding;
response.setContentType(fullContentType);
if (noCache) {
// Http 1.0 header
response.setDateHeader("Expires", 1L);
response.addHeader("Pragma", "no-cache");
// Http 1.1 header
response.setHeader("Cache-Control", "no-cache, no-store, max-age=0");
}
return response;
}
/**
* @description 獲取磁盤物理路徑
* @return String
*/
protected String getRealPath() {
return request.getSession().getServletContext().getRealPath("");
}
/**
* @description 得到session對象
* @return Session
*/
protected HttpSession getSession() {
return this.request.getSession();
}
/**
* @Title: getParams
* @Description: 得到頁面所有參數(shù)
* @return Map
* @throws
*/
public Map getParameters() {
return ActionContext.getContext().getParameters();
}
/**
* @description 設(shè)置session對象Attribute屬性
* @param key
* @param value
*/
protected void setSessionAttribute(String key, Object value) {
sessionMap.put(key, value);
}
/**
* @description 返回session對象的Attribute屬性
* @param key
* @return Object
*/
protected Object getSessionAttribute(String key) {
return sessionMap.get(key);
}
/**
* @description 清除整個session
*/
protected void clearSession() {
sessionMap.clear();
}
/**
* @description 清除session中指定的內(nèi)容
* @param key
*/
protected void remove(Object key) {
sessionMap.remove(key);
}
/**
* @description 通過request獲取頁面參數(shù)值
* @return string
*/
protected String getParameters(String name) {
return (null != request.getParameter(name)) ? request
.getParameter(name) : null;
}
/**
* @description 獲取項目根目錄
* @return String
*/
protected String getRootPath() {
return request.getContextPath();
}
/**
* @description 獲取request獨享
* @return
*/
public HttpServletRequest getRequest() {
return request;
}
/**
* @description 獲取response對象
* @return
*/
public HttpServletResponse getResponse() {
return response;
}
/**
* @description 獲取sessionMap
* @return
*/
public Map getSessionMap() {
return sessionMap;
}
public String getTarget() {
return target;
}
public void setTarget(String target) {
this.target = target;
}
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public void setSession(Map sessionMap) {
this.sessionMap = sessionMap;
}
}
解析:1.接到上面struts2的配置問題來說,可以看到我們在配置result的時候存在占位參數(shù)${target},那這個target是哪里來的?可以看到,BaseAction中已經(jīng)包含這個變量,并且提供get方法,有童鞋會問為什么這樣子對target設(shè)置就能替換${target},我只能說這是OGNL的一種機制。
2.可以看出baseAciton中定義了很多常量,怎么用?這些常量定義是為了處理response的響應(yīng)頭,上面我有講過,我沒有在struts.xml中處理流返回類型,json返回類型,對吧?很顯然是要在這里做操作了撒,可以看出有很多render開頭的重載方法,這些方法就是幫助我們直接去響應(yīng)前臺,后面例子中我會附帶系統(tǒng)中struts2對json處理、對流文件(excel、img)處理。
3.實現(xiàn)了很多接口,值得注意的是Preparable和ModelDriven。注意這個BaseAction是泛型,就是因為
的interceptor攔截前臺參數(shù),把參數(shù)分裝成我們指定的泛型類型的對象,而Preparable則是提供給一個預(yù)處理接口,讓在執(zhí)行Action方法之前執(zhí)行。其他幾個幾口是幫助我們獲取作用域?qū)ο?,session、request。
示例我寫得很簡單,大概就是舉例一下,如何進行前后臺的交互,以及響應(yīng)不同返回類型。由于帖子長度有限,所以基類的代碼何示例代碼大家只有下載了,寫這篇文章耗費了我3個小時,由于文筆水品有限,有瑕疵的地方,請大家指正批評。