Struts最佳实践

架构——异地多活成熟的架构模式 摘要: 本文系统介绍了三种异地多活架构模式:业务定制型、业务通用型和存储通用型。业务定制型针对核心业务定制化设计,复杂度低但扩展性差;业务通用型通过统一配套服务(流量调度、配置中心等)实现多业务兼容,适合业务量大但一致性要求不高的场景;存储通用型依托分布式一致性数据库(如OceanBase、TiDB)天然支持强一致性,适合金融等高要求场景,但对部署距离和成本有较高限制。文章对比了各模式的优缺点及适用场景,为不同业务需求下的架构选型提供了实践指导。 阅读详情

背景:

      从本期的电子杂志内容介绍中,大家已经看到了web发展的整个历史,  

      Struts 自从 2001 6月1.0 Release之后经历了漫长的春秋,有着庞大的用户群体, 并且IBM, Tomcat Web控制台都采用了Struts Framework..

      web框架有好多种选择,并不一定要使用Struts, 但如果你正刚开始使用的话,希望下面的一些实践能给你带来帮助, 仅此而已.  所以,请原谅,本文没有什么实例代码, 因为今天早上,我的好友Leemassn 跟我说,这东西已经烂掉了:( ,所以相信基本用法你们了解的比我多,也并没有涉及到一些高级用法, 我下面所说的内容, 也均属纸上谈兵.

1. 正确是导向,才是使用Web Framework的真正目的.

   并不时因为Struts 耳儒目染的多了,我们才一定要使用Struts ,并不时MVC就一定要使用Struts ,当你能灵活游刃于StrutsActionForm ,Action ,Lib之间, "疏能跑马,密不透风"  而且能够扩展的你的Web 框架时,之后才是我们运用框架的真正灵便之处.

 

    先说一些与Struts 无关的话题,因为Struts并不能取代你应用框架的全部,无论项目大或小,复杂或者简单

一些建议:

 1. 请选用支持广泛的JDO  或者Hibernate,或者iBates,来做你的数据持久层,

 2. 请加入Struts-el标签,

 3. 请选用应用服务器的JNDI连接数据库

 4. 请使用StrutsTestCase做单元测试

 5. 请阅读sun 的命名规范.

 

1.Struts 之对象使用篇

   Struts 版本换了好多了,,如果你只是使用最基本的Form,Action相信0.5 就够了,但眼下大家用的都是1.1吧 

    每写个应用都用继承BaseAction ,和BaseForm , 当然BaseAction 最好是继承LookupDispatchAction, BaseForm 最好是继承ValidatorActionForm (这两个都是从1.1开始有的)

      

  ValidatorActionForm也是继承ActionForm ,   因为1.1有了PlugIn,当你使用ValidatorPlugIn使得你的FormBean具备了验证能力啦.  

 

  (1.1 也同时 DynaActionForm ,相信大家都知道这个Bean,但它似乎除了让你少写一些ActionForm之外没什么用处,除非你是想完全不给予ActionForm,这样偶尔用到ActionForm的时候也可以小用一把DynaActionForm, 看来Struts对自己的ActionForm似乎没有多信息,欲弃欲留,我们都知道ActionForm 是不能完全充当Model(Model已应该是你的持久层)的,那我们至少可以用它来传值吧,方便支出就是不需要 一个个表单内容去get ,再set了.所以,我们有必要使用ActionForm , 同时我们也要对每个属性进行用户端的输入校验,于是我们选用ValidatorActionForm.)

 

     LookupDispatchAction 继承DispatchAction, 自己多加两个方法,就是getKeyMethod(),localMap ,它能帮你 从本地submit的资源文件,比如submite 的名字是add 就能找到你的add方法.

 

 

2.Struts 之标签库篇.

   相信Struts是很讲究复用的

  标签库主要还是用做View的,所以,在设计ActionForm的时候大可大胆设计,别担心他们不能在jsp页面上很好的显示, 该是Data类型就是,也可以使用List,Map ,这样的符合类型,也可以是引用对象类型,因为他们能很方便的在页面上显示

    如果Test1Form包含了 各种Model对象,

   Test1Form{

        Student student      //有id,name等属性

        Teach teach    //有id, classid等属性

        List classes   //一组Classes 对象 Classes又含有 classid等属性

        Test2Form test2form --- //有 attr2 等property

        ....

     }   

     那么

      <html:form action="/test1">
     <bean:define name="test1Form" property="test2Form" id="test2"
                type="com.yourcompony.Test2Form" />
      <html:text  name="test2" property="test2.
attr2" />

         <html: text name="studentsid" property="student.id">

         <html: text name="techname" property="teach.name">

         <html: text name="classid" property="classes[0].classid">
   </html:form >
 

  看到了,它们其实什么都能得到,发挥你的想象标签库能展示你的任何对象属性值.

    记得在ActionForm reset里初始化一下,并且依次得到对象.这样你同样能把这些内容全部递交给ActionServlet. 如果没使用过这些,赶紧试试吧.

   

     尽量使用EL标签: 主要用于复杂的逻辑判断,

   举个例子 <logic:present name="yourForm" property="a"> 判断了a是否存在,但你又想知道a 是否等于1,怎么样头痛了吧,换成el 那就是 <c:if test='${yourForm.a =="1" }'>  ....</c:if>

  

    补充一些:对于前台的显示,,Struts标签不得不说是似乎已经成了一根鸡肋,  美丽,容易操作的的界面,往往要以来于其他技术,Struts的标签使用的最大的目的也是为了方便于数据显示, 美丽复杂操作还是要依赖你的Html与JavaScript.

 

3.Struts 之异常处理篇.

      基本上来讲,Struts 给异常处理提供了较为完善的框架.

      按道理讲,当一个系统正式交付的时候,,我们还让用户看到那些 一大串英文字母是一种极端粗暴的行为, 所以,我们从两头专起.

      1.使用validationForm做可验证的确formBean , 当然你也可以使用你积累下来比较丰富的javascript,无论那种方式,都有一点会让你受益,就是学会使用正则表达.

      2.Action处理中,在try catch 使用saveMessage 使用saveErrors()或者saveMessaes是,因为(Struts1.2开始抛弃了ActionErrors,全部是ActionMessages了)

       

         这里就不得不说到一些构架上的一些东西了. Struts Action中处理的异常,已经不该是你的原始异常了.在你的Dao层要抛出DataException,而在你的业务层,需要捕获到,作为你的自定义异常抛出,这样你在struts里捕获到的异常才是友好的,且是有意义的.

    我们都知道Dao那一层都是抛一个统一的异常比如DataExpcetion ,

   然后到你的业务处理 Service 那一层能就捕获DataExpcetion, 因为Serivce那一层,你总归是知道自己要做什么, 因此建议在Service 那层捕获DataException 之后,打印 debug日志, 然后再抛出业务逻辑异常

   比如在业务处理,添加一个学生过程,如果

          public void doAddStudent(Student student) throws DupKeyExption,Ser{

      try{

              if((Student)load(student.getId()).getId()==student.getId()){

                throw new DupKeyExcption("改同学已经存在");

              }

              studentDao.add();

          }catch(DataException e){

            logger.debug("错误信息:",e);

            throws new StudentException("增加失败");

          }

        }

 

    try {

            service.doAddStudent();

       }catch (DupikeyException e1){

           //重复添加了

      errors.add("message",new ActionError("student.error.dupkey"));

        }catch (Exception e) {

           //添加失败

                 errors.add("message",new ActionError("student.error.add"));

          logger.error(e.getMessage());

          e.printStackTrace();

        }

        saveErrors(request, errors);

 

    

    至于显示嘛,直接使用<html:errors/>就OK了.但是你要觉得没有空白的地方显示,也可以使用

    <html:messages id="message">

       <script language=javascript>window.alert('<bean:write name="message"/>')</script>

    </html:messages>

  对于,全局的异常,那你最好forward一个 gloable-forward 的 showErorr.jsp之类的jsp

  (注:Struts1.2开始,抛弃了ActionErrors了,统一使用使用ActionMessages了 error其实是个多余的对象,用法一样)

 

4 Struts 之 扩展篇

    Struts 的Plugin 给Struts应用程序算是留了一到后门,扩展Struts 可以由此窃入

     Plugin 能使得你的web应用程序在startup或shutdown 的时候,能完成一部分操作. 它是基于配置的,你可以很方便的外挂一些应用程序,

    比如HibernatePlugin

    public class HibernatePlugIn implements PlugIn {
    

    public static final String SESSION_FACTORY_KEY
            = SessionFactory.class.getName();

    private static Log _log = LogFactory.getLog(HibernatePlugIn.class);

    private boolean _storedInServletContext = true;
    private String _configFilePath = "/hibernate.cfg.xml";

    private ActionServlet _servlet = null;
    private ModuleConfig _config = null;
    private SessionFactory _factory = null;

    /**
     * Destroys the <code>SessionFactory</code> instance.
     */
    public void destroy() {
        _servlet = null;
        _config = null;
       
        try {
            _log.debug("Destroying SessionFactory...");
           
            _factory.close();
           
            _log.debug("SessionFactory destroyed...");
        } catch (Exception e) {
            _log.error("Unable to destroy SessionFactory...(exception ignored)",
                    e);
        }
    }
   
    /**
     * Initializes the <code>SessionFactory</code>.
     * @param servlet the <code>ActionServlet</code> instance under which the
     *        plugin will run.
     * @param config the <code>ModuleConfig</code> for the module under which
     *        the plugin will run.
     */
    public void init(ActionServlet servlet, ModuleConfig config)
    throws ServletException {
        _servlet = servlet;
        _config = config;
       
        initHibernate();
    }
   
    /**
     * Initializes Hibernate with the config file found at
     * <code>configFilePath</code>.
     */
    private void initHibernate() throws ServletException {
        Configuration configuration = null;
        URL configFileURL = null;
        ServletContext context = null;
       
        try {
            configFileURL = HibernatePlugIn.class.getResource(_configFilePath);

            context = _servlet.getServletContext();

            if (_log.isDebugEnabled()) {
                _log.debug("Initializing Hibernate from "
                        + _configFilePath + "...");
            }
           
            configuration = (new Configuration()).configure(configFileURL);
            _factory = configuration.buildSessionFactory();
           
            if (_storedInServletContext) {
                _log.debug("Storing SessionFactory in ServletContext...");
               
                context.setAttribute(SESSION_FACTORY_KEY, _factory);
            }
          
        } catch (Throwable t) {
            _log.error("Exception while initializing Hibernate.");
            _log.error("Rethrowing exception...", t);
           
            throw (new ServletException(t));
        }
    }
   
    /**
     * Setter for property configFilePath.
     * @param configFilePath New value of property configFilePath.
     */
    public void setConfigFilePath(String configFilePath) {
        if ((configFilePath == null) || (configFilePath.trim().length() == 0)) {
            throw new IllegalArgumentException(
                    "configFilePath cannot be blank or null.");
        }
       
        if (_log.isDebugEnabled()) {
            _log.debug("Setting 'configFilePath' to '"
                    + configFilePath + "'...");
        }
       
        _configFilePath = configFilePath;
    }
   
    /**
     * Setter for property storedInServletContext.
     * @param storedInServletContext New value of property storedInServletContext.
     */
    public void setStoredInServletContext(String storedInServletContext) {
        if ((storedInServletContext == null)
                || (storedInServletContext.trim().length() == 0)) {
            storedInServletContext = "false";
        }
       
        if (_log.isDebugEnabled()) {
            _log.debug("Setting 'storedInServletContext' to '"
                    + storedInServletContext + "'...");
        }
       
        _storedInServletContext
                = new Boolean(storedInServletContext).booleanValue();
    }
   
}

 

5. 测试篇

   Struts通过传统的手工输入进行测试, 效率教低, 请尽量使用单元测试

   

基本使用如下

public class BaseActionTest extends MockStrutsTestCase {

public StudentActionTest(String arg0) {

super(arg0);

}

 

public static void main(String[] args) {

junit.textui.TestRunner.run(UserActionTest.class);

}

 

public void setUp() throws Exception {

super.setUp();

    setContextDirectory(new File("E://webapp//webContext"));

}

protected void tearDown() throws Exception {

    super.tearDown();

}

 

public void testAdd() {

setRequestPathInfo("/student");

addRequestParameter("method","add");

actionPerform(); //执行

verifyForward("success");

 

}

}

YOLOv8改进系列:RepVGG重参数化结构——训练多分支,推理单路,极致提速 本文将详细介绍如何将RepVGG的重参数化思想融入到YOLOv8的骨干网络中,实现一种训练时多分支、推理时单路的改进版YOLOv8。我们将提供完整的代码实现、详细的原理讲解,并在COCO数据集和自定义数据集上进行充分的实验验证。 阅读详情

相关推荐

SLAM工程师面试避坑指南:2025年最新高频考点与实战代码解析

本文为SLAM工程师提供2025年最新面试避坑指南,涵盖高频技术考点如VINS初始化、三维几何处理、多传感器融合架构设计等,并包含实战代码解析。特别针对算法工程师面试中的常见陷阱,提供系统设计框架和代码模板,帮助求职者提升通过率。

metaverse5vr的博客 246

Struts 开发的最佳实践

Struts:简介 Struts 是一种开源框架,可用来构建 Web 应用程序,它基于流行的 Model-View-Controller (MVC2) 设计范型。该框架构建在一些标准的技术之上,比如 Java Servlets、JavaBeans、ResourceBundles 和 XML,并且可提供灵活和可扩展的组件。Struts 以 ActionServlet 的形式实现了 Co...

流浪的代码 128

东方马达步进电机AZM66AK-HS100+AZD-KD调试经验记录

东方马达步进电机AZM66AK-HS100+AZD-KD调试经验记录(20170803YC) 本次总结主要实现的功能如下:用MEXE02软件在步进电机驱动器中设置好控制动作,每个控制动作有一个特定的编号。之后通过PC和驱动器之间的485通讯,发送相关指令,使步进电机按照一定编号的控制动作运转。 参考资料:东方马达步进电机AZM66AK-HS100+AZD-KD的产品手册,可在官网下载。 A....

dahailuoa6的博客 1万+

Struts 开发的最佳实践,在 Web 应用程序开发中优化 Struts 框架

Struts:简介 Struts 是一种开源框架,可用来构建 Web 应用程序,它基于流行的 Model-View-Controller (MVC2) 设计范型。该框架构建在一些标准的技术之上,比如 Java Servlets、JavaBeans、ResourceBundles 和 XML,并且可提供灵活和可扩展的组件。Struts 以 ActionServlet 的形式实现了 Controll...

zhangziyangup 151

wsl2 配置ubuntu 固定ip

wsls ubuntu 设置固定ip

musk1212的博客 2618

控制科学与工程(自动化)保研经验【4】——浙大篇

控制科学与工程(自动化)保研经验【4】——浙大篇

Control Everything 1万+

终于体验到"struts formbean的最佳实践是String"这句话的强大意义了

这断时间一直在用struts做开发,还规定尽量用struts的标记库,所以最进对struts的标记库研究得比较多。直到今天才发现,前面研究的东西都是白费了,最终都是用不上了。 前面写过用struts tag对formbean 属性的显示,花了不少时间研究出了对Integer ,BigDecimal类型属性的显示问题,struts formbean是不支持Date类型的属性的。也看到了”struts...

付出总比收获快乐 141

《派出你的AI同事:WorkBuddy案例实战》067:按行业分类的案例索引

按行业分类的案例索引 —— 《派出你的AI同事:WorkBuddy案例实战》系列文章,配图已统一为规范示意图。

LuckyHanMo的博客 101

开发最佳实践:在Web应用开发中优化Struts框架

摘自:http://developer.51cto.com/art/201004/195352.htm 本文向您讲解了如何使用灵活的Struts框架调节Web应用程序开发。这里向您展示了一些最佳实践,您可以遵循这些实践来优化这个成熟的开源框架。此外,您还可以学习使用一些十分有价值的标准Struts组件,包括 ActionForm、Action 类和 ActionErrors。 AD:201...

weixin_30338743的博客 144

Vue + ECharts:从零构建智慧农业数据监控大屏(附完整源码)」 「超实用!一步步实现智慧农业大屏,完整代码+讲解」 「前端新手友好:Vue + ECharts 打造炫酷农业数据大屏」 「

Vue + ECharts:从零构建智慧农业数据监控大屏(附完整源码)」 「超实用!一步步实现智慧农业大屏,完整代码+讲解」 「前端新手友好:Vue + ECharts 打造炫酷农业数据大屏」 「前端可视化项目实战:智慧农业监控大屏开发详解」 「农作物可视化监控:用 Vue 和 ECharts 构建大屏应用」 「从零开始开发一个智慧农业数据大屏(代码+图表展示)」 「前端新手也能实现!智慧农业监控大屏开发教程」 「用 Vue 和 ECharts 搭建动态数据大屏:详细图文教程」 「学习前端大屏开发:

sky10100100的博客 1535

【AI智能体】Claude Code +Superpowers 项目实战操作详解

Claude Code +Superpowers 项目实战操作详解

congge 4054

struts2的多国语言实现最佳实践

在struts2 中的Localization这章中,讲述了很多实现多国语言的方法,我在使用中也感觉到了struts给我们带来的巨大便利,我这里选择一种较为复杂,也非常使用的一种实践办法。上面的 i18n_en.properties 和 i18n_zh.properties是全局的资源文件,这里其实可以包含大部分的中英文信息,是非常重要的2个文件,而BookTypeAction.propertie

品品观 3420

Mac 下 OpenClaw 安装全记录:从零到一的保姆级图文教程

本文主要介绍了Mac 下 OpenClaw 安装全记录:从零到一的保姆级图文教程,希望能对学习使用OpenClaw 的同学们有所帮助。 文章目录 1. 背景 2. 安装教程 2.1 安装OpenClaw 2.2 配置模型 2.3 对话 3. 后续使用步骤 4. 关闭程序

weixin_43178406的博客 11万+

Struts2、Spring、Hibernate 高效开发的最佳实践

简介 Struts2、Spring、Hibernate(SSH)是最常用的 Java EE Web 组件层的开发技术搭配,网络中和许多 IT 技术书籍中都有它们的开发教程,但是通常的教程都会让很多程序员陷入痛苦的配置与修改配置的过程。本文利用 SSH 中的技术特性,利用 Java 反射技术,按照规约优于配置的原理,基于 SSH 设定编写了一个通用开发框架,这使得开发者可以专注于业务逻...

baiqiao1870的博客 288

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Struts2、Spring、Hibernate 高效开发的最佳实践(转载)

Struts2、Spring、Hibernate 高效开发的最佳实践 Struts2、Spring、Hibernate(SSH)是最常用的 Java EE Web 组件层的开发技术搭配,网络中和许多 IT 技术书籍中都有它们的开发教程,但是通常的教程都会让很多程序员陷入痛苦的配置与修改配置的过程。本文利用 SSH 中的技术特性,利用 Java 反射技术,按照规约优于配置的原理,基...

weixin_33688840的博客 108

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Struts2,spring,hibernate高效开发的最佳实践

简介:Struts2、Spring、Hibernate(SSH)是最常用的 Java EE Web 组件层的开发技术搭配,网络中和许多 IT技术书籍中都有它们的开发教程,但是通常的教程都会让很多程序员陷入痛苦的配置与修改配置的过程。本文利用 SSH中的技术特性,利用 Java 反射技术,按照规约优于配置的原理,基于 SSH设定编写了一个通用开发框架,这使得开发者可以专注于业务逻辑的开发,而...

爱java 187

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

atitit.Atitit. Gui控件and面板-----服务端控件 java struts的实现最佳实践

atitit.Atitit.  Gui控件and面板-----服务端控件 java struts的实现最佳实践   1. 服务器控件的类别 1 1.1. 数据控件:该类控件可细分为两种类型:数据源控件和数据绑定控件。 1 1.2. 站点导航控件: 1 1.3. WebParts控件: 1 1.4. 登录控件: 1 1.5. Ajax 控件 1 2. jsf 2 3. Apache  ecs 2...

weixin_34060741的博客 140
上一篇: Servlet规范简介——web框架是如何注入到Servlet中的
下一篇: Java Web Framework综述
emag_java
博客等级 码龄22年 29粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值