写写,看看

 
 

常用链接

  • 我的随笔
  • 我的文章
  • 我的评论
  • 我的参与
  • 最新评论

留言簿(1)

  • 给我留言
  • 查看公开留言
  • 查看私人留言

文章档案(3)

  • 2007年12月 (3)

搜索

  •  

最新评论

  • 1. re: 一个Singleton的问题!!help!!
  • 把你这部分相关的代码贴出来,有时间帮你看看!
  • --wuming
  • 2. re: 一个Singleton的问题!!help!!
  • 没有用过 Fortify,帮你聚一下人气
  • --jeasonzhao
  • 3. re: 一个Singleton的问题!!help!!
  • 有没有人能够帮助一下,提些建议!
  • --lala

Powered by: 博客园
模板提供:沪江博客
BlogJava | 首页 | 发新随笔 | 发新文章 | 联系 | 聚合 | 管理

2007年12月14日

ActionServlet(2)

本文按照1.构造函数->2.init()->3.do*()->4.destroy()的顺序,解析ActionServlet的工作原理。
init()的初始化工作分为个步骤进行:
1.initInternal()资源文件的初始化

protected String internalName = "org.apache.struts.action.ActionResources";
protected void initInternal(){
internal 
= MessageResources.getMessageResources(internalName);//初始化资源文件信息,通过工厂模式取得一个单例的资源
}


internalName与initInternal()都是protected所以可以被子类重载。修改struts默认的资源文件信息。
2.initOther()根据web.xml的配置参数执行不同的初始化,1.设置struts配置文件路径2.convertNull

protected void initOther()throws ServletException {
        String value;
        value 
= getServletConfig().getInitParameter("config");
        
if (value != null) {
            config 
= value; //设置struts配置文件路径
        }
     
        value 
= getServletConfig().getInitParameter("convertNull");
        
if ("true".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value)
            
|| "on".equalsIgnoreCase(value) || "y".equalsIgnoreCase(value)
            
|| "1".equalsIgnoreCase(value)) {
            convertNull 
= true;
        }

        
if (convertNull) { //如果convertNull为true\on\yes\y\1执行
            ConvertUtils.deregister();
            ConvertUtils.register(
new BigDecimalConverter(null),BigDecimal.class);
           ……
        }

    }

  
3.initServlet()解析servletName,url-Pattern。官方struts的web.xml:servletName=action,urlPattern=/*.do

 

protected void initServlet()throws ServletException {         
        
this.servletName = getServletConfig().getServletName();//取得设置servletName
        /**//*digester主要是实现对xml的访问,许多功能强大的常用操作都已经封装了起来。*/
        Digester digester 
= new Digester();
        digester.push(
this);
        digester.setNamespaceAware(
true);
        digester.setValidating(
false);
        
for (int i = 0; i < registrations.length; i += 2) {
            URL url 
= this.getClass().getResource(registrations[i + 1]);
            
if (url != null) {
                digester.register(registrations[i], url.toString());
            }

        }

        
/**//*以下3句的意思是当遇到web-app/servlet-mapping时执行addServletMapping函数(下面有该函数的源码),这个方法有两个参数,第一个是web-app/servlet-mapping/servlet-name标签里的,第二个是web-app/servlet-mapping/url-pattern标签里的.parse (input)开始解析。实际上这段陌生的代码只是执行了addServletMapping(servlet-name,url-pattern);servlet-name,url-pattern分别从/WEB-INF/web.xml中取得*/
        digester.addCallMethod(
"web-app/servlet-mapping", "addServletMapping", 2);
        digester.addCallParam(
"web-app/servlet-mapping/servlet-name", 0);
        digester.addCallParam(
"web-app/servlet-mapping/url-pattern", 1);
        InputStream input 
=
            getServletContext().getResourceAsStream(
"/WEB-INF/web.xml"); 
        digester.parse(input);        
        
if (servletMapping != null) {
            getServletContext().setAttribute(Globals.SERVLET_KEY, servletMapping);
        }

    }

    

 

/**//*在initServlet()中被调用*/
    
public void addServletMapping(String servletName, String urlPattern) {
        
if (servletName == null) {
            
return;
        }

        
/**//*一般而言servletName=action,urlPattern=/*.do*/
        
if (servletName.equals(this.servletName)) {
            
if (log.isDebugEnabled()) {
                log.debug(
"Process servletName=" + servletName
                    
+ ", urlPattern=" + urlPattern);
            }


            
this.servletMapping = urlPattern;
        }

    }

 

(初始化工作还未完成,待续)
posted @ 2007-12-14 00:44 lala 阅读(175) | 评论 (0) | 编辑 收藏
 

2007年12月13日

ActionServlet(1)
     ActionServlet是对应于原始java web开发中的servlet,是struts最核心的类。在实际的编程中,ActionServlet出现的次数很少,甚至不需要知道它便可以完成一个小型的项目,由此可见引入一个厉害框架将减低对技术的要求。
    在项目开发中,ActionServlet的出现最少只需要1次,便是在web.xml中。
    
<servlet>
        
<servlet-name>action</servlet-name>
        
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>         
    
</servlet>
    
<servlet-mapping>
        
<servlet-name>action</servlet-name>
        
<url-pattern>*.do</url-pattern>
    
</servlet-mapping>

    不知道被复制了多少遍的一段代码,今天我终于狠下心要来揭开他的秘密!
    ActionServlet继承于HttpServlet,所以可以安全的放在web.xml的</servlet-clss>标签里。在原始的java web开发中,HttpServlet的init()\destroy() \service() \do*()函数经常需要根据业务继承实现。同样的,在ActionServlet里,它继承实现了这几个方法,从这个意义上讲ActionServlet与原始web开发中的servlet没有任何的区别。
     ActionServlet就是一个HttpServlet的特殊实现,所以要真正了解ActionServlet流程必须知道HttpServlet的流程。
     HttpServlet的流程应该包括:1.构造函数->2.init()->3.do*()->4.destroy()。
     init()的执行时间有两种方式:1.Tomcat启动时2.在提交到该Servlet时 (可以通过<load-on-startup>进行设置)
   
     同样的在ActionServlet中,也是由这几个函数来是实现web服务的,只是它所实现的并不是业务服务代码,而是控制代码。  
     
posted @ 2007-12-13 01:18 lala 阅读(109) | 评论 (0) | 编辑 收藏
 

2007年12月8日

一个Singleton的问题!!help!!
       最近在做一些代码安全性检查,使用了Fortify。发现了一些曾经引以为豪的代码既然会出现高危的错误。希望各位达人给予帮助。
         设计初衷:共享WebApplicationContext,通过getBean(String beanName)取得对应的bean处理相应的业务逻辑。
public class BaseAction extends Action {
    
private WebApplicationContext wac;
    
protected ServletContext context;    
    
public void setServlet(ActionServlet actionServlet) {
        
super.setServlet(actionServlet);
        context 
= actionServlet.getServletContext();
        wac 
= WebApplicationContextUtils.getRequiredWebApplicationContext(context);
    }


    
protected Object getBean(String beanName) {
        
return wac.getBean(beanName);
    }

}
      高危错误代码:        
context = actionServlet.getServletContext();
        wac 
= WebApplicationContextUtils.getRequiredWebApplicationContext(context);
         错误原因分析:BaseAction继承自Action,单例实现。该类含有属性:wac与context,在多线程环境下不能保证这两个属性的合理逻辑。于是掉入了一个单例模式的陷阱。(请各位达人完善)
         解决方法:jdon(banq)给我的回复          
       
 banq:写的方法是高危,但是看你的方法内容,则没有关系。

你的方法内容是获得一个Web项目的一个单例,实际就是Spring容器,而且大部分是读,而不是读写并加。

单例陷阱我已经在以前帖子中说了,只有在单例+写+同步等操作下才可能死锁,因为代码不可控性,今天你注意没这么做,不代表其他无知的人不这么做,所以,这种singlton会被严谨的工具认为是高危,这是正确的。
 ME:谢谢 banq!
如果需要消除这段高危代码,需要如何重构.
因为只是存在读操作,我是否可以把wac与context定义为static(这样工具不会报错)

请问这样改会不会有问题?
  banq:不能用static,这样Spring容器中所有资源都不能随着你的WEB项目消失而消失。

主要问题在于你的setServlet(ActionServlet actionServlet)这个方法,这其实是一个初始化工作,试验在BaseAction的构造方法中首先实现,这样表示有前有后,可能不会报高危错误。

实在不行,做一个懒加载的方法,在这个方法中,检查一下wac是否为空,如果为,就进行初始化,不为空,就直接返回wac值。
去除setServlet方法,在getBean加入,如下,如果还不行,就每次老老实实的用WebApplicationContextUtils获得Spring实例:

protected Object getBean(String beanName) {
if(wac==null){
context 
= actionServlet.getServletContext();
wac 
= WebApplicationContextUtils.getRequiredWebApplicationContext(context);
}


return wac.getBean(beanName);
}


                 
posted @ 2007-12-08 00:56 lala 阅读(373) | 评论 (3) | 编辑 收藏
 
仅列出标题