Struts2 入门
很久没有看Java相关的东西了,这几天才发现Struts2 已经发布了,以前就听说Struts2就是以前的Webwork2,只是作了少许的改动而已,我以前也没看过Webwork,所以赶紧下来试了一把。
Struts2的地址:http://struts.apache.org/2.x
在Eclipse中新建了一个Tomcat工程(如果用WTP插件的话Dynamic Web工程)struts2Test,以下是添加了Library后的工程截图。
Struts2支持spring,tiles等很多技术,如果要使用,则相应的插件struts2-***-plugin.jar应该包含在classpath中,为了简单我使用struts2-all.jar。实际上用tiles的时候发现有些问题,可能是版本匹配不对,后来我采用了sitemesh来代替tiles,用sitemesh似乎比tiles更简单。
首先,应该设置好web.xml,要使用Struts2+sitemesh,需依次设置3个filter,最后一个listener是spring的。为了使用struts2和sitemesh的标签,我把标签文件单独拷了出来。
< web-app id ="Struts2" version ="2.4" xmlns ="http://java.sun.com/xml/ns/j2ee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >
< display-name > Struts2 </ display-name >
< filter >
< filter-name > Struts2-cleanup </ filter-name >
< filter-class > org.apache.struts2.dispatcher.ActionContextCleanUp </ filter-class >
</ filter >
< filter-mapping >
< filter-name > Struts2-cleanup </ filter-name >
< url-pattern > /* </ url-pattern >
</ filter-mapping >
< filter >
< filter-name > sitemesh </ filter-name >
< filter-class > com.opensymphony.module.sitemesh.filter.PageFilter </ filter-class >
</ filter >
< filter-mapping >
< filter-name > sitemesh </ filter-name >
< url-pattern > /* </ url-pattern >
</ filter-mapping >
< filter >
< filter-name > struts2 </ filter-name >
< filter-class > org.apache.struts2.dispatcher.FilterDispatcher </ filter-class >
</ filter >
< filter-mapping >
< filter-name > struts2 </ filter-name >
< url-pattern > /* </ url-pattern >
</ filter-mapping >
< listener >
< listener-class > org.springframework.web.context.ContextLoaderListener </ listener-class >
</ listener >
< welcome-file-list >
< welcome-file > index.html </ welcome-file >
</ welcome-file-list >
<!--
This typically isn't required, as the taglib is included in struts-core.jar.
If you really need a taglib configuration within web.xml,
copy struts2-core/core/src/main/resources/META-INF/struts-tags.tld
to the WEB-INF directory as struts-tags.tld.
-->
< taglib >
< taglib-uri > /sitemesh-page </ taglib-uri >
< taglib-location > /WEB-INF/sitemesh-page.tld </ taglib-location >
</ taglib >
< taglib >
< taglib-uri > /sitemesh-decorator </ taglib-uri >
< taglib-location > /WEB-INF/sitemesh-decorator.tld </ taglib-location >
</ taglib >
< taglib >
< taglib-uri > /struts-tags </ taglib-uri >
< taglib-location > /WEB-INF/struts-tags.tld </ taglib-location >
</ taglib >
</ web-app >
要使用spring来为Struts2提供IOC,需要在源码包中的struts.properties设置objectFactory属性。
struts.custom.i18n.resources = globalMessages
struts.objectFactory = spring
struts.objectFactory.spring.autoWire = type
struts.ui.theme = simple
为了使用Struts2提供的i18n功能,定义了一个全局的资源文件globalMessages.properties,其内容就不给出了,该文件也放在源码包中。另外,Struts2还缺少一个配置Action的文件strtus.xml,该文件也放在源码包中;再在WEB-INF目录下新建一个spring的配置文件applicationContext.xml和sitemesh的配置文件decorator.xml。两个文件的类容分别如下,我就不解释了:
<! DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
< beans default-autowire ="autodetect" >
< bean id ="dataSource"
class ="org.springframework.jdbc.datasource.DriverManagerDataSource" >
< property name ="driverClassName" >
< value > com.mysql.jdbc.Driver </ value >
</ property >
< property name ="url" >
< value > jdbc:mysql://localhost:3306/forum </ value >
</ property >
< property name ="username" >
< value > test </ value >
</ property >
< property name ="password" >
< null />
</ property >
</ bean >
< bean id ="sessionFactory"
class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
< property name ="dataSource" >
< ref local ="dataSource" />
</ property >
< property name ="mappingResources" >
< list >
< value > cn/tju/lzy/forum/model/User.hbm.xml </ value >
< value > cn/tju/lzy/forum/model/Article.hbm.xml </ value >
< value > cn/tju/lzy/forum/model/Board.hbm.xml </ value >
</ list >
</ property >
< property name ="hibernateProperties" >
< props >
< prop key ="hibernate.dialect" >
org.hibernate.dialect.MySQLDialect
</ prop >
< prop key ="hibernate.show_sql" > true </ prop >
< prop key ="hibernate.cache.provider_class" >
net.sf.ehcache.hibernate.SingletonEhCacheProvider
</ prop >
</ props >
</ property >
</ bean >
< bean id ="transactionManager"
class ="org.springframework.orm.hibernate3.HibernateTransactionManager" >
< property name ="sessionFactory" >
< ref local ="sessionFactory" />
</ property >
</ bean >
< bean id ="userDAO"
class ="cn.tju.lzy.forum.dao.hibernate.UserDAOHibernate" >
< property name ="sessionFactory" >
< ref local ="sessionFactory" />
</ property >
</ bean >
< bean id ="boardDAO"
class ="cn.tju.lzy.forum.dao.hibernate.BoardDAOHibernate" >
< property name ="sessionFactory" >
< ref local ="sessionFactory" />
</ property >
</ bean >
< bean id ="articleDAO"
class ="cn.tju.lzy.forum.dao.hibernate.ArticleDAOHibernate" >
< property name ="sessionFactory" >
< ref local ="sessionFactory" />
</ property >
</ bean >
< bean id ="loginAction" singleton ="true"
class ="cn.tju.lzy.forum.action.LoginAction" >
< property name ="userDAO" >
< ref local ="userDAO" />
</ property >
</ bean >
< bean id ="registAction" singleton ="true"
class ="cn.tju.lzy.forum.action.RegistAction" >
< property name ="userDAO" >
< ref local ="userDAO" />
</ property >
</ bean >
</ beans >
< excludes >
< pattern > /decorators/main.jsp </ pattern >
</ excludes >
< decorator name ="main" page ="main.jsp" >
< pattern > * </ pattern >
</ decorator >
</ decorators >
新建一个struts2的Action,完成regist功能,通常Action都继承自ActionSupport类。
import cn.tju.lzy.forum.dao.UserDAO;
import cn.tju.lzy.forum.model.User;
import com.opensymphony.xwork2.ActionSupport;
public class RegistAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L ;
private String name = null ;
private String password = null ;
private String password2 = null ;
private String email = null ;
private UserDAO userDAO = null ;
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println( " execute() calling in LoginAction. " );
if (userDAO.isUserExist(getName())) {
addActionError(getText( " user.name.exist " ));
return INPUT;
} else {
User user = new User();
user.setName(name);
user.setPwd(password);
user.setEmail(email);
userDAO.saveUser(user);
return SUCCESS;
}
}
@Override
public void validate() {
if (getName() == null || getName().length() < 1 ) {
addFieldError( " name " ,getText( " user.name.empty " ));
}
if (getPassword() == null || getPassword().length() < 1 ) {
addFieldError( " password " ,getText( " user.password.empty " ));
}
if (getPassword2() == null || getPassword2().length() < 1 ) {
addFieldError( " password2 " ,getText( " user.password2.empty " ));
}
if (getPassword() != null &&! getPassword().equals(getPassword2())) {
addFieldError( " password2 " ,getText( " user.password.password2.unequal " ));
}
}
public UserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(UserDAO userDAO) {
this .userDAO = userDAO;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this .email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this .password = password;
}
public String getPassword2() {
return password2;
}
public void setPassword2(String password2) {
this .password2 = password2;
}
}
当然还要一些页面文件,以regist.jsp为例:
<% @ taglib uri = " /sitemesh-decorator " prefix = " decorator " %>
<% @ taglib uri = " /struts-tags " prefix = " s " %>
< html >
< head >
< title > regist </ title >
</ head >
< body >
< center >
< div style ="color:red" align ="left" >< s:actionerror /></ div >
< s:form method ="POST" action ="regist" >
< table border ="0" width ="600" >
< thead bgcolor ="#CCCCCC" >
< font size ="5" > < b > < s:text name ="user.regist.form" /> </ b > </ font >
</ thead >
< tr >
< td height ="40" width ="100" align ="right" >< s:text
name ="user.name" /></ td >
< td >< s:textfield name ="name" size ="20" /></ html:text ></ td >
< td height ="40" align ="left" valign ="center"
style ="color:red;font-size:18" >< s:fielderror >
< s:param > name </ s:param >
</ s:fielderror ></ td >
</ tr >
< tr >
< td height ="40" width ="100" align ="right" >< s:text name ="user.password" /></ td >
< td >< s:password name ="password" size ="20" /></ td >
< td height ="40" align ="left" valign ="center"
style ="color:red;font-size:18" >< s:fielderror >
< s:param > password </ s:param >
</ s:fielderror ></ td >
</ tr >
< tr >
< td height ="40" width ="100" align ="right" >< s:text name ="user.password2" /></ td >
< td >< s:password name ="password2" size ="20" /></ td >
< td height ="40" align ="left" valign ="center"
style ="color:red;font-size:18" >< s:fielderror >
< s:param > password2 </ s:param >
</ s:fielderror ></ td >
</ tr >
< tr >
< td height ="40" width ="100" align ="right" >< s:text name ="user.email" /></ td >
< td >< s:textfield name ="email" size ="30" /></ td >
< td height ="40" align ="left" valign ="center"
style ="color:red;font-size:18" >< s:fielderror >
< s:param > email </ s:param >
</ s:fielderror ></ td >
</ tr >
< tr >
< td height ="40" width ="100" align ="right" ></ td >
< td >< s:submit value ="%{getText('button.submit')}" /> < s:reset
value ="%{getText('button.reset')}" /> < s:submit
value ="%{getText('button.cancel')}" action ="welcome" ></ s:submit ></ td >
< td height ="40" align ="right" ></ td >
</ tr >
</ table >
</ s:form ></ center >
</ body >
</ html >
最后,来看一下struts.xml
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd" >
< struts >
< package name ="cn.tju.lzy.forum.action" namespace ="/"
extends ="struts-default" >
< action name ="welcome" >
< result > /pages/index.jsp </ result >
</ action >
< action name ="*_input" >
< result > /pages/{1}.jsp </ result >
</ action >
< action name ="regist"
class ="cn.tju.lzy.forum.action.RegistAction" >
< result name ="input" > /pages/regist.jsp </ result >
< result name ="success" type ="redirect-action" > login </ result >
</ action >
< action name ="login"
class ="cn.tju.lzy.forum.action.LoginAction" >
< result name ="input" > /pages/login.jsp </ result >
< result name ="success" type ="redirect-action" > welcome </ result >
< result name ="cancel" type ="redirect-action" > welcome </ result >
</ action >
</ package >
</ struts >
实际上将原来的ActionForm和Action合并了,这也许也是Struts2带来的最大变化吧,这样肯定比以前的编写两个类简单了。对于另外的一些功能像拦截器、转化器、验证等我还没有尝试,大家可以参考一下这个网址:http://www.blogjava.net/max/category/16130.html