[转]一些struts开发技巧

Struts 配置文件定义
   对于系统中的某个模块,需要在开发前定义该模块的配置,该 struts 的配置文件命名为:
   struts-config-xxx.xml
   xxx 为模块的小写英文名或缩写,如: struts-config-sysman.xml
   注意:中间为“ - ”,而不是“ _ ”连接符
   统一保存在“ WEB-INF/xml ”文件夹下,并需要在 web.xml 中添加相应的配置文件
   地址,具体如下例:
   …
   <init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/struts-config.xml, /WEB-INF/xml/struts-config-pages.xml,/WEB-INF/xml/struts-config-sysman.xml</param-value>
   </init-param>
          注意:需要用“,”连接符隔开各个配置文件名
   另外,所有的静态 jsp 需要通过配置文件定义其“ .do ”形式的访问,保存在
   struts-config-pages.xml 文件中,内容如下例:
   …
   <!-- 主页转向 -->
   <action path="/main" type="org.apache.struts.actions.ForwardAction" parameter="/main.jsp"/>
   …


Tiles 配置文件定义
   系统的框架配置文件为 tiles-defs_zh_CN.xml (通过 .properties 属性文件支持国际化应用,默认是 tiles-defs.xml ),模块的框架结构需要定义在里面,如下例:
   …
   <!-- 定义默认首页 -->
   <definition name="default.frame" path="/layouts/defaultLayout.jsp">
   <put name="title" value=" 欢迎进入电信经营分析系统 " />
   <put name="header" value="/top.jsp" />
   <put name="body" value="default.body" />
   <put name="footer" value="/buttom.jsp" />
   </definition>
   <!-- 定义默认首页的 body -->
   <definition name="default.body" path="/layouts/main.jsp" >
   <put name="logon" value="/logon.jsp" />
   <put name="date" value="/layouts/date.jsp" />
   <put name="linkSite" value="/layouts/link.html" />
   </definition>
   …
   框架命名规范按“系统(子系统) . 功能模块 . 页面模块 ”,如上面的“ default.frame ”
   在 struts-config-pages.xml 文件中的设置的页面 action 可以这样写:
   <action path="/main" type="org.apache.struts.actions.ForwardAction" parameter=" default.frame "/>
   这样就不必单独写一个 tiles:insert 的页面,如下:
   <tiles:insert definition="vip.warn.day" flush="true" />


模块中的注释
   不但需要在程序中添加必要的注释,在定义配置文件的时候也必须需要添加相应注释,主要是在 struts-config-xxx.xml 和 tiles-defs_zh_CN.xml 这些文件中添加注释,要把 action 或配置模块的功能解释清楚,放在配置项的前面,参见上面的配置文件


对于配置文件的编辑
   不能使用 Jbuilder 里面的 xml 编辑功能,因为 JB 会自动地改变 xml 里面的编码和内容,因此,对 xml 配置文件的编辑,要使用编辑软件,如 UE 等
   事件定义
   事件对应的类主要有 Action 、 ActionForm ,还有 jsp 中提交的“ .do ”定义,以及页面动作的提交,以 login 登录为例:
   1. 类的命名定义(首字母需大写)
   形式为“动作名 +Action/Form ”
   如: LoginAction.class 、 LoginForm.class
   2. 页面地址定义(首字母需小写)
   如果有两个单词以上,第二个单词首字母大写,依此类推
   形式为“动作名”
   如: login.do 或 loginSys.do
   jsp 文件命名也按此规范
   3. 页面动作定义
   因为 jsp 页面中的 Form 对应 ActionForm ,其本身有 action 这个属性,所以页面动作如果定义也为 action ,会引起不必要的麻烦,所以,把页面动作统一定义为“ act ”,
   如需要编辑某条记录,地址如下:
   “ /editRecord.do?act= Edit ”
   如需要删除,地址如下:
   “ /editRecord.do?act=Delete ”
   4. 对于菜单和操作事件触发的控制机制
   由于系统中的菜单和操作都是由“ .do ”形式向服务端发请求的,因此需要一套机制来控制哪些是对菜单的事件请求,哪些是对操作的事件请求;
   我们在系统中引入了 Filter 过滤器,对所有请求进行控制,以及判断用户是否登录和是否有对资源(菜单等)访问权限等;
   约定:
   jsp 页面上对于系统中菜单的请求都是“ GET ”方法,对于操作的 Action 都是“ POST ”方法;
   有了这样的约定,在 Filter 中先判断 request 的请求方法,如果是“ GET ”方法,则认为是对菜单的请求,所以去“菜单表”根据请求地址读取相应的记录,并读取用户的权限表,判断用户的菜单权限;
   如果是“ POST ”的方法,则认为是对操作的请求,并提取 request 中的“ act ”动作,进行对用户的权限点的判定。
  
参数信息获取
   1. 公共参数信息通过 Plugin 方式在 Web 服务启动时将变量放入 application 中,使得在任何需要该变量的 jsp 中都可以调用;
   方式如下:
   public void setServletContext(ActionServlet actionServlet) {
   try {
   ServletContext sc = actionServlet.getServletContext();
   //SysInitPwd
   sc.setAttribute(Constants.SYS_INIT_PWD,SelectLists.getSysConfig("PWDINIT"));
   …
   在 action 等程序中的调用方式:
   getServlet().getServletContext().getAttribute(“…”);
  
   2. 对于页面上需要展示的数据尽量存放在 request 这个范围里,可以减轻服务器端内存负载,方式如下:
   // 调用员工处理类
   StaffDeal sd=new StaffDeal();
   // 根据员工状态查询员工
   ArrayList al=sd.qryStaff(strState);
   // 放入 request
   request.setAttribute("staffInfo",al);
   3. 私有的或需要根据用户的属性来获取参数信息的,可以在 tiles 的定义中使用“ controlClass=xxx ”这个方式获取,配置如下例:
   <definition name="vip.welcome" path="/vip/welcome.jsp" controllerClass="viptx.logic.vip.welcomeAction" />
   需 implements Controller 中的 perform 方法,代码如下例:
   public void perform(ComponentContext componentContext,
   HttpServletRequest request,
   HttpServletResponse response,
   ServletContext servletContext) throws IOException,ServletException {
   HttpSession session = request.getSession();
   // Get current session.
   User user = (User) session.getAttribute(Constants.USER_KEY);
   if (user == null) {
   return null;
   }
   String uid = user.getUserid();
   String sql = "select userid,content from ti_salutatory where userid='"+uid+"'";
   try {
   …
   }
   catch (Exception ex) {
   throw new ServletException(ex.getMessage());
   }
   }
   4. 对于后台出错信息在前台页面显示的技巧
   首先在 properties 配置“ message.common={0} ”
   然后在 Action 类中使用 ActionErrors 或 ActionMessages 时,方法如下:
   …
   ActionMessages ams = new ActionMessages(); // 例外处理
   Try{
   …
   }
   catch (Exception ex) {
   ex.printStackTrace();
   ams.add(ActionMessages.GLOBAL_MESSAGE,
   new ActionMessage("message.common", ex.getMessage()));
   }
   finally {
   if (!ams.isEmpty()) {
   saveMessages(request, ams);
   }
   }
   …
   在 jsp 页面中使用方法如下:
   <html:messages id="msg" message="true">
   <font color="red"><bean:write name="msg"/></font>
   </html:messages>
   如果有后台的 messages 产生,前台页面就可以出现报错信息


系统配置文件
   系统参数如数据库连接等在 sysConfi.xml 文件中配置,存放在“ WEB-INF/xml ”文件夹下,请参见该文件。
   开发规范和公用方法
   关于 java 的开发规范参见《 Java 编程规范 .doc 》,这里仅给出用 struts 开发中一些的规范:
   1. java 文件存放按业务逻辑划分,并用模块作为包名的形式,如: telecombi.logic.sysman.security
   包名都为小写形式
   所有的 Action 和 ActionForm 都存放在同一包下,便于管理,不要跨包调用
   2. 所有 ActionForm 中的属性均为“首单词小写 + 第二个单词首字母大写 +… ”的形式,如: staffId 、 staffName ,不允许使用“ _ ”为单词连接符
   3. 需要验证的页面,均需要客户端和服务端两次验证(即对 jsp 中的 Form 进行 javascript 验证和 Action 中的 excute 方法中进行验证),不能只采用其中一种方法,防止客户绕过 js 直接提交;
   在验证登录提交的 form 时,必须使用 staticJavascript="false" ,否则就会把 javascript 写到页面里,如:
   <html:javascript formName="logonForm"
   dynamicJavascript="true"
   staticJavascript="false"/>
   <script language="Javascript1.1" src="staticJavascript.jsp"></script>
   验证的 formName 必须和 validation.xml 中的 Form 的名字对应起来,否则验证无效
   4. ActionForm 是代表 html 中的 Form 的,其中的变量需要和 Form 中的属性对应起来,如:要在 jsp 中使用 <form:text property="userName"/> ,则使用的 ActionForm 中就必须有 userName 这个变量
   5. 对于 Action 中的逻辑,如果处理方法在一个以上,需要另外新建一个处理类,负责对 Action 中的逻辑集中处理,命名为 xxxDeal ,如: LoginDeal;
   Action 通过调用该处理类的方法,实现业务逻辑处理
   6. 对数据库的操作使用 DBManager 这个类,对其中的一些方法,具体介绍如下:
   n 查询结果对象化的 Select 操作,使用 Select(String sql,String className) 方法
   StringBuffer sql = new StringBuffer(
   "select staff_id staffId from ts_m_staff ")
   .append("where staff_id='").append(uid).append("'");
   try {
   /**
   * User 是一个用户对象类,其中有 staffId 这个属性,以及对应的 get/set 方法,通过
   * DBManager 的 Select 方法获得一个 User 的 ArrayList 集合
   */
   ArrayList rs = DBManager.Select(sql.toString(), User.class.getName());
   /**
   * 如果确定返回的只有一个对象,则可以使用
   *
   */
   User user=(User)rs.get(0);
   }
   catch (Exception ex) {
   throw new ServletException(ex.getMessage());
   }
   取出来的数据可以存放在 session 或 page 等里,供 jsp 页面调用,方法为 session.setAttribute(“user”,user1)
   …
   n Insert 或 Update 等操作
   使用 DBManager 里面的 executeSql(String sql) 方法,如果是批量处理,使用 executeBatchSql(String[] sqls) 方法,返回成功标志为 Constants.OPERATE_SUCCESS
   失败标志为 Constants.OPERATE_FAILED
   暂无其它信息返回
   n ResultSet 对象向 Hashtable 集合对象的转化,使用 select(String sql) 方法:
   除了可以使用 DBManager 的 Select 把查询结果转为对象以外,还可以使用以前的直接使用 ResultSet 对象的方式,不过这里返回的数据集对象为 Hashtable ;
   Hashtable 存放的数据结构为:
   columnName1 — ArrayList1( 该字段的结果集 )
   columnName2 — ArrayList2( 该字段的结果集 )
   …
   系统中使用该方法的比较多的是用在生成下拉框数据,从 select 方法返回的 Hashtable 取到字段值,并生成 LabelValueBean ,具体方法如下:
   /** 公用函数 Hashtable 转换成 ArrayList (LabelValueBean)*/
   private static ArrayList hashToLVB(Hashtable ht, String id, String name,boolean hasBlank) {
   if (ht!=null){
   ArrayList al = new ArrayList();
   ArrayList alId = (ArrayList) ht.get(id.toUpperCase());
   ArrayList alName = (ArrayList) ht.get(name.toUpperCase());
   int iLen = alId.size();
   if (hasBlank)
   al.add(new LabelValueBean(" 未知 ", "-1"));
   for (int i = 0; i < iLen; i++) {
   al.add(new LabelValueBean( (String) alName.get(i),
   (String) alId.get(i)));
   }
   return al;
   }
   else{
   return null;
   }
   }
   n AutoSetForm ( String sql, Object frm )方法介绍:
   a) 该方法可以返回一个查询数据库后已对其中的属性赋值的对象,使用方法如下:
   User user=DBManager. AutoSetForm(sql, new User() );
   sql 为查询语句
   b) 该方法还可以对页面操作后的 Form 进行赋值,比如在页面上提交一个对某条记录进行编辑的操作,当 Action 得到该条记录的 Id 号并查询数据库成功后,需要把各个详细信息 set 到 ActionForm 的属性变量中去,这个时候就可以使用该方法,方法如下:
   form= DBManager. AutoSetForm(sql,form);
   form 为 Action 的 excute 方法中传入的 ActionForm
  
          7.调用存储过程
   使用 DBManager 中的 execProc(String procName,ArrayList procPrts) 方法
   procName 为存储过程名, procPrts 是该存储过程的入口参数集,返回的是 ProcOuts 的对象,其中有 Result 和 ExceptionInfo 两个属性,表示返回的处理标记和异常信息(如果有的话)
   8. 数据操作返回信息的处理
   在对数据操作完成后,需要返回操作是否成功等信息,具体步骤如下:
   n 使用属性文件中的“ messages.comm ”这个 key ,可以对该 key 添加具体返回信息
   n 程序中使用“ ActionMessages ”这个对象, java 程序如下:
   ActionMessages ams = new ActionMessages();
   …
   // 执行结果
   ProcOuts pResult=null;
   // 是否调用成功
   if (pResult.getResult() == -1) {
   ams.add(ActionMessages.GLOBAL_MESSAGE,
   new ActionMessage("message.common",
   pResult.getExceptionInfo()));
   }
   if (!ams.isEmpty()) {
   saveMessages(request, ams);
   }
   Jsp 中调用方法如下:
   <html:messages id="msg" message="true">
   <font color="red"><bean:write name="msg"/></font>
   </html:messages>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值