【前言】所谓快速开发,实质上为了节省项目的开支成本,减少程序员的开发时 间,固然就形成了种种二次封装的框架,也就是造轮子,然后我们的程序就按照这个轮子去画瓢,这里我就把公司这几次开发系统的框架源码贴出来,做一下讲解以 及使用示范,并有附件提供参考,希望能给各位在基于后台管理系统提供帮助。
【目录】
        1.struts2的配置
        2.struts2的基类构成
        3.具体实例应用
【内容】         
 一、struts2的配置
    1 .struts2的过滤器拦截配置 :相信大家对struts2的配置一定不陌生,这里我就简单带过struts2过滤器在web.xml的配置:

<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
     2 .struts2全局配置:这里我要做一点介绍了,按常理来讲,我们都是基于约定大于配置的原则,不做重复劳动的思想:

A.基于Annotation的配置(struts2有一种叫convention的插件,可以实现零配置,具体可以百度Struts2 convention,我就不做讲解,注:这里的零配置是针对struts2在xml中配置)。
        B.采用通配符进行配置,也就是我推荐的,也是我们项目中用到的一种方法,先上代码struts.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="default" namespace="/" extends="struts-default"> <global-results>
<result name="error">/page/error.jsp</result>(1)
<result name="input"></result>(1)
<result name="login" type="redirect">/login.jsp</result>(1)
<result>${target}</result>(2)
<result type="redirectAction" name="redirectAction">${target}</result>(2)
<result type="redirect" name="redirect">${target}</result>(2)
</global-results>
</package>
<package name="app" namespace="/" extends="default">(4)
<action name="*/*/*" class="st.{1}.web.{2}Action" method="{3}">(3)
</action>
</package>
</struts>

解 析:上面我对配置文件中加入(1)、(2)、(3)、(4),表示对此处的标注,下面我就对这些部分进行解析。                                                               (1):如果有用过struts2的童鞋,可以清晰的看出它们名称都很有含义,对没错 struts2的Action类已经封装这4个静态常量,当我们在Action的方法中完成操作后,要对视图进行 跳转或者响应时,要返回一个字符串,比如:return SUCCESS;那么这个SUCCESS实际上就是对应我们在struts2配置的xxxx.jsp,简化一下也就是xxx.jsp,默认的result name就是"success" 默认的type是dispatch 也就是JSP视图,那么这样我们就可以对这些预定好的变量配置他们响应的跳转视图页面。
            (2)

:很奇怪为什么有个${target},${target}只是作为struts2的配置的占位参数,而基类BaseAction中我们存放了一个
target变量,当解析struts.xml时,可以从我们实现类中读   
取出来,然后进行替换,这样做的好处是什么,很显然,我们要返回的jsp页面有成千上万种,我不可能每次都去配置 a.jsp  
b.jsp....,这样可以说是实现了统一设置路径,也就是通配,而且还有不同类型的返回,type="redirect"/
type="redirectAction",看上去好像是一样的,区别在于redirectAction可以指定重定向到某个action上
(struts2中配置的action),target就是Action的name,值得注意的是我这里只是罗列了重定向以及Jsp视图的类型,要知道还
有其他N多种类型的视图,怎么办?我先把关于模板类型的返回的告知出来以freemaker为例,其他见基类BaseAction:
         struts.xml 中加入freemaker" name="freemaker">${target} ,其实道理是一样 只是type不一样而已,target="xxxx.ftl";
             (3):这个是很重要的,我们所有的action都用了通用,原则是:{模块名}/{用例名}/{方法}.action
            比如:st.sys.web.UserAction.java - sttbas_server/src/java这样一个类,我们访问它的查询方法:sys/User/view.action,很简单。
             (4):我们这个名为app的package继承了 default包,也就意味可以重用default的配置。
            好
像struts.xml少了点什么东西,对我们没有配置它的属性,这里我们将struts2的属性配置进行区分,也是官方推荐的设置将
struts.xml,与struts.properties分开,并放入classpath目录下,struts.properties内容如下:

#允许使用下划线#
struts.enable.SlashesInActionNames=true //必须要的,因为我们配置Action时用了下划线
#spring做为对象管理工厂#
struts.objectFactory=spring 
#开发模式#
struts.devMode=false//开发阶段可以开启这个模式
#静态缓存#
struts.serve.static.browserCache=false //开发阶段可以开启
#配置是否重新加载#
struts.configuration.xml.reload=true //建议开启,方便调试,发布版本的时候可以关闭

当然还有很多属性的配置,详细可以参考struts2源码包中struts.properties
二、struts2的基类

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";
// -------------------- 作用域对象 --------------------//
/** sessionMap对象 */
private Map sessionMap;
/** request对象 */
private HttpServletRequest request;
/** response对象 */
private HttpServletResponse response;
/** ajax消息 */
public static final AjaxMsg ajaxMsg = new AjaxMsg();
// --------------------视图跳转路径------------------//
/**
* 例如:"index.jsp index.ftl"
*/
private String target;
// -- Preparable函数 --//
/**
* 实现空的prepare()函数,屏蔽了所有Action函数都会执行的公共的二次绑定.
*/
public void prepare() throws Exception {
}
// -------------绕过jsp/freemaker直接输出文本函数-------------//
// -- 绕过jsp/freemaker直接输出文本的函数 --//
/**
* 直接输出内容的简便函数. 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数组,目前接受的值为"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转换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);
}
/**
* 分析并设置contentType与headers.
*/
private static HttpServletResponse initResponseHeader(
final String contentType, final String... headers) {
// 分析headers参数
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();
// 设置headers参数
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: 得到页面所有参数
* @return Map
* @throws
*/
public Map getParameters() {
return ActionContext.getContext().getParameters();
}
/**
* @description 设置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中指定的内容
* @param key
*/
protected void remove(Object key) {
sessionMap.remove(key);
}
/**
* @description 通过request获取页面参数值
* @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的时候存在占位参数${target},那这个target是哪里来的?可以看
到,BaseAction中已经包含这个变量,并且提供get方法,有童鞋会问为什么这样子对target设置就能替换${target},我只能说这是
OGNL的一种机制。 
        2.可以看出baseAciton中定义了很多常量,怎么用?这些常量定义是为了处理response
的响应头,上面我有讲过,我没有在struts.xml中处理流返回类型,json返回类型,对吧?很显然是要在这里做操作了撒,可以看出有很多
render开头的重载方法,这些方法就是帮助我们直接去响应前台,后面例子中我会附带系统中struts2对json处理、对流文件(excel、
img)处理。
        3.实现了很多接口,值得注意的是Preparable和ModelDriven。注意这个BaseAction是泛型,就是因为ModelDriven(模型驱动),有了它我们可以直接由ModelDriven的interceptor拦截前台参数,把参数分装成我们指定的泛型类型的对象,而Preparable则是提供给一个预处理接口,让在执行Action方法之前执行。其他几个几口是帮助我们获取作用域对象,session、request。
        4.附件中会包含基类的引用类,JsonUtil(json工具类)以及AjaxMsg(ajax消息类,针对Json消息)

三、具体示例
        示例我写得很简单,大概就是举例一下,如何进行前后台的交互,以及响应不同返回类型。由于帖子长度有限,所以基类的代码何示例代码大家只有下载了,写这篇文章耗费了我3个小时,由于文笔水品有限,有瑕疵的地方,请大家指正批评。

四、附件地址
http://pan.baidu.com/share/link?shareid=2838805807&uk=2701872319

《项目架构那点儿事》——浅析web层struts2的构建的更多相关文章

  1. 《项目架构那点儿事》——Hibernate泛型Dao,让持久层简洁起来

    [前言]hibernate作为持久层ORM技术,它对JDBC进行非常轻量级对象封装,使得我们可以随心所欲的使用面向对象的思想来操作数据 库.同时,作为后台开发的支撑,的确扮演了一个举足轻重的角色,那么 ...

  2. 《项目架构那点儿事》——快速构建Junit用例

    [前 言]按照惯例,在实际项目中我往往会对自己编写的程序进行测试,当测试通过后才能将其用于实战中,当然,编写单元测试是不可避免的,可以直接清晰的检验出 我们程序的可靠性.可只执行性,从中发现问题从而得 ...

  3. IDEA项目搭建二——使用SpringBoot创建Web层

    一.编写底层代码 1.demo-common中创建FormatString类 先在默认com.tyh中创建package命名为common 删除自动生成的app.java,在common包下创建新类 ...

  4. .net大型平台通过Nginx做负载均衡(Web层、中间服务层、DB层)

    .net平台下,我目前部署过的均衡负载有两种方式(iis7和Nginx),以下以Nginx为例讲解web层的均衡负载. 简介:Nginx 超越 Apache 的高性能和稳定性,使得国内使用 Nginx ...

  5. [译]ABP框架使用AngularJs,ASP.NET MVC,Web API和EntityFramework构建N层架构的SPA应用程序

    本文转自:http://www.skcode.cn/archives/281 本文演示ABP框架如何使用AngularJs,ASP.NET MVC,Web API 和EntityFramework构建 ...

  6. mvc项目架构搭建之UI层的搭建

    项目架构搭建之UI层的搭建 Contents 系列一[架构概览] 0.项目简介 1.项目解决方案分层方案 2.所用到的技术 3.项目引用关系 系列二[架构搭建初步] 4.项目架构各部分解析 5.项目创 ...

  7. 项目架构开发:数据访问层之Cache

    数据访问层简单介绍 数据访问层,提供整个项目的数据访问与持久化功能.在分层系统中所有有关数据访问.检索.持久化的任务,最终都将在这一层完成. 来看一个比较经典的数据访问层结构图 大概可以看出如下信息 ...

  8. Web应用程序系统的多用户权限控制设计及实现-项目架构【3】

    本章主要讲述Web权限管理系统的项目架构,及开发中需要的基本类和相关的CSS,JS文件. 1.1系统结构 本系统搭建开发工具为Visual Studio 2012,采用ASP.NET MVC 4.0技 ...

  9. 项目架构开发:数据访问层之Logger

    接上文 项目架构开发:数据访问层之Cache 本章我们继续ILogger的开发 ILogger.cs public interface ILogger { void Info(object messa ...

随机推荐

  1. 深入理解C# 静态类与非静态类、静态成员的区别 [转载]

    静态类 静态类与非静态类的重要区别在于静态类不能实例化,也就是说,不能使用 new 关键字创建静态类类型的变量.在声明一个类时使用static关键字,具有两个方面的意义:首先,它防止程序员写代码来实例 ...

  2. MyEclipse的JQuery.min.js报错红叉解决办法

    MyEclipse的JQuery.min.js报错红叉解决办法 1.选中报错的jquery文件"jquery-1.2.6.min.js".2.右键选择 MyEclipse--> ...

  3. flex的三个属性:

    (1)flex-grow:指的是相对于其他的子元素的扩展比率:默认值为0:数字 (2)flex-basis:指的是子元素的具体长度:可以为长度(rem,px,em)也可以为百分比: (3)flex-s ...

  4. 51nod 1593 公园晨跑 | ST表(线段树?)思维题

    51nod 1593 公园晨跑 有一只猴子,他生活在一个环形的公园里.有n棵树围绕着公园.第i棵树和第i+1棵树之间的距离是 di ,而第n棵树和第一棵树之间的距离是 dn .第i棵树的高度是 hi ...

  5. win8.1 安装

    下载了Windows8.1企业版的iso文件,文件名称:cn_windows_8_1_enterprise_x86_dvd_2791409.iso 下载地址: http://msdn.itellyou ...

  6. Python C++扩展

    Python C++扩展 前段时间看了一篇文章,http://blog.jobbole.com/78859/, 颇有感触,于是就结合自己工作中的知识作了一个简单的Python移动侦测:移动侦测的算法使 ...

  7. python中sys.exit()和os._exit(0)退出程序

    python中退出程序的两种方法,0为默认状态,可以为空,两者均会退出当前运行的程序,os._exit(0)中的0不能省略 sys.exit(0):可以捕获SystemExit异常,然后做相应的清理工 ...

  8. Noip2016组合数(数论)

    题目描述 组合数表示的是从n个物品中选出m个物品的方案数.举个例子,从(1,2,3) 三个物品中选择两个物品可以有(1,2),(1,3),(2,3)这三种选择方法.根据组合数的定 义,我们可以给出计算 ...

  9. Spring bean 生命周期验证

    一.从源码注释看bean生命周期 从JDK源码上看,BeanFactory实现类需要支持Bean的完整生命周期,完整的初始化方法及其标准顺序(格式:接口 方法)为: 1.BeanNameAware s ...

  10. 如何通过C#操作Access,本人亲测通过

    1. c# 操作access数据库 // it's your DB file path: // ApplicationEXEPath\Test.mdb var DBPath = "d:\\T ...