配置SSH的一种实践方法(Spring,Struts2,Hibernate)

近来做了一个小项目,用到了SSH,自己配了下,记录下怕以后忘了。

 

第一步当然下载建工程下JAR包,我用MAVEN,个人觉得比较方便。贴下我用的版本。

 

<spring.version>3.1.1.RELEASE</spring.version>
        <struts2.version>2.3.12</struts2.version>
        <hibernate.version>4.1.0.Final</hibernate.version>

 工程好了,就配相关的东西了。

STRUTS2:

 

其实主要是struts.xml的配置。具体可以看代码。我就写点配的时候记得比较清楚的。

1. Action,Convention配置。

    Convention就是让我们可以少写点代码,但是要配点规则上去,大体意思是告诉STRUTS2去那里找JSP,去那找ACTION.

      a. 确保你打开了struts2扫描

<constant name="struts.convention.action.disableScanning" value="false"/>

    b.告诉strus2扫描那个包

<constant name="struts.convention.package.locators.basePackage" value="com.demo.action"/>

  c. 如果要踢出一些不想扫描的包

<constant name="struts.convention.exclude.packages"
    value="org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate.*"/>

  d. 如果你用JOBSS6,有时候你会有点伤,都照网上的配了,就是不OK,怎么办。也许下面的配置对你有用。

<constant name="struts.convention.action.fileProtocols" value="jar,vfs,vfsfile,vfszip,"/>
    <bean type="org.apache.struts2.convention.ActionConfigBuilder" name="myActionConfigBuilder"
          class="com.demo.utils.MyActionConfigBuilder"/>
<constant name="struts.convention.actionConfigBuilder" value="myActionConfigBuilder"/>

   就是JBOOS用的vfs,还有在扫描的时候好像有点问题。不知道新的解决这个问题没有。当时要写一个actionconfigbuild.有兴趣可看源代码。

   e.Struts2里要配个package.

<package name="basic-package" extends="tiles-default,json-default" namespace="/">   </package>

     因为项目主用到tiles和json这两种类型的result,所以继承一下。

 

     f. 上ACTION代码了,终于

    我一般习惯写一个基类,让他类继承,也好方便我以后控制

public class BasicAction extends ActionSupport

     然后再所有action都继承这个

    

@Controller
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Namespace(BasicAction.BASE_NAME_SPACE)
public class ProductAction extends BasicAction {

   @Controller是spring一个annoation,我在这里先写上,因为用了spring ioc,后面配的时候再会说到。

     @Scope(BeanDefinition.SCOPE_PROTOTYPE)这个一定要,因为spinrg默认是对所有bean是单例的, 加个这个就是每个都是一个新的实体。

       @Namespace(BasicAction.BASE_NAME_SPACE)我action放在子包里面所以要加这个,不然URL会变成sub-package-name/action-name.

 

   写个action:

 

@Action(value = "index",
            results = {@Result(name = SUCCESS, type = "tiles", location = ".createProduct")})
    public String iniProC() throws Exception {
        return SUCCESS;
    }

2.  Tiles 配置:

   上面在家可以看到type是tiles,对了,接下来配tiles.主要是tiles.xml

        Tiles主要解决很多网站会很好的分成上中下三块,每次action会有不同的组和,通过一个XML可以很好的把相关的JSP关连起来。

     

定一个基本的模板。
   <definition name=".bodyCenter" template="/jsp/layout/layoutOfBody.jsp">
        <put-attribute name="header" value="/jsp/layout/header.jsp"/>
        <put-attribute name="contentHeader" value="/jsp/layout/userheader.jsp"/>
        <put-attribute name="bottom" value="/jsp/layout/footer.jsp"/>
</definition>
有时要一个简单的模板:
   <definition name=".simple" extends=".bodyCenter">
        <put-attribute name="header" value=""/>
        <put-attribute name="contentHeader" value=""/>
        <put-attribute name="bottom" value=""/>
    </definition>
具体实现:
    <definition name=".createProduct" extends=".simple">
        <put-attribute name="contentBody" value="/jsp/demo/product/create.jsp"/>
    </definition>

 上代码吧,我还是觉得代码比文档更适合用于CODER之间的交流

 3. 验证

Struts2分客户端和服务端的。

   a. 服务端:

      服务端验证就是提交到服务器了再验证,也有两种,一种直接写个方法,struts2会根据名子的规则在调用具体方法之前调用验证方法。比方说你要给一个叫save的ACTION方法加验证,你定义validateSave方法就OK,有ERROR就加到addFieldError("password", "两次密码不一致");这个方法就不细说了。

当然也可以用XML和annotation 我觉是太多annotation在CLASS也不太好看,我就选择了XML 

            方法就是在类下面加一个这样的XML:

           actionName-methodName-validation.xml

           里面写你要验证的东东:

 

        

<validators>
    <field name=" user.nickName">
        <field-validator type="required">
            <message key="user.nickname"></message>
        </field-validator>
    </field>
</validators>

       b.再说一下JS客户端的配法吧

 

<constant name="struts.ui.theme" value="simple"/>

      想用客户端验证,一定不能用simple.请用其他的主题。比方说css_xhtml。因为struts要包一下input框才好后面加error message.但这功能很容易导致UI变开,我后来没用了。要是有CSS高手可能写一个一变开的主题那还是比较好的。比方说error message可以变成一个气泡谈出来之类了.总之大家慎用。

                        还要加个<s:head />,因为是JS验证嘛,这里面有好多JS会include

4. 国际化

   a. 文字:我想大家从资源文件读就OK了,一般问题不大,如果在JAVA里面也有相应的方法可以读取

  b. 时间时区:这个会比较坑爹一点,主要看你怎么设计了,我当时只有一台应用服务器,所以我使用的方法是,把服务器改成UTC,这样就不会有跨天的问题,session中保存一下用户的时区,每次显示或上传的时候都会根据这个时区做相应用的改变,这样整个容器里都UTC了,再也不用时区的问题心烦了

    显示:

<tag>
    <description><![CDATA[Render a formatted date.]]></description>
    <name>date</name>
    <tag-class>my.utils.CalenderTag</tag-class>
    <body-content>empty</body-content>
    <attribute>
      <description><![CDATA[Date or DateTime format pattern]]></description>
      <name>format</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <description><![CDATA[Deprecated. Use 'var' instead]]></description>
      <name>id</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <description><![CDATA[The date value to format]]></description>
      <name>name</name>
      <required>true</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <description><![CDATA[Whether to print out the date nicely]]></description>
      <name>nice</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <description><![CDATA[The specific timezone in which to format the date]]></description>
      <name>timezone</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <description><![CDATA[Name used to reference the value pushed into the Value Stack]]></description>
      <name>var</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <dynamic-attributes>false</dynamic-attributes>
  </tag>
protected void populateParams() {
        super.populateParams();
        Date d = (Date) component;
        d.setName(name);
        d.setFormat(format);
        d.setNice(nice);
        Float timeZoneFloat = (Float) ActionContext.getContext().getSession().get("timeZone");

        if (timeZoneFloat == null) {
            timezone = "GMT+08:00";
        } else {
            timezone = formatFloatToTimeZone(timeZoneFloat);
        }
        d.setTimezone(timezone);
}

    上传,写个convert:

java.util.Calendar=my.utils.DateConverter

    加到xwork-conversion.properties里面DateConverter里面重要的方法。

    

public Object convertFromString(Map context, String[] values, Class toClass) {

        Calendar cal = Calendar.getInstance();
        Date date = null;
        String dateString = values[0];

        DateFormat format = null;
        for (int i = 0; i < ACCEPT_DATE_FORMATS.length; i++) {
            format = ACCEPT_DATE_FORMATS[i];

            try {
                if (i == 4) {
                    date = new Date();
                    cal.setTime(date);
                    cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(dateString.substring(0, 2)));
                    cal.set(Calendar.MINUTE, Integer.parseInt(dateString.substring(3, dateString.length())));
                    Utils.changeTimeZoneForIn(cal);
                } else {
                    date = format.parse(dateString);
                    cal.setTime(date);
                    Utils.changeTimeZoneForIn(cal);
                }
                return cal;
            } catch (Exception e) {
                continue;
            }
        }
        return null;
    }

 5。 最一差点忘记了,web.xml里面一定要配置filter和tag,就不贴了看源代码吧

我想说的struts2 让人配起来好累。下次找个时间把它做了。自己写个

文章长了写的人累,看的人更累,别外两个配置放到其他一个BLOG里吧。

 

Strut MVC 源代码

相关推荐