??xml version="1.0" encoding="utf-8" standalone="yes"?> 1、用xml方式Q?br />struts2配置 <bean id="userAction" class="org.han.action.LoginAction" scope="prototype" > 2、struts2使用雉|方式: 3、struts2、spring都用注解方式: <context:component-scan base-package=""/>用此U方式,不需要在配置文g中再配置beanQ也不需要再导入上面对应的处理bean。也是说可以不需要在配置文g中?lt;context:annotation-config/>了,因ؓ此种方式会自动导?/p>
[java] @Scope用于定义Bean的作用范围?/p>
@Autowired 注释Q它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。当 Spring 容器启动ӞAutowiredAnnotationBeanPostProcessor 扫?Spring 容器中所?BeanQ当发现 Bean 中拥?@Autowired 注释时就扑ֈ和其匚wQ默认按cd匚wQ的 BeanQƈ注入到对应的地方中去。所以对成员变量使用 @Autowired 后,您大可将它们?setter Ҏ删除?/p>
@Qualifier(“name”) 中的 name?Bean 的名Uͼ所?@Autowired ?@Qualifier l合使用Ӟ自动注入的策略就?byType 转变?byName 了。@Autowired 可以Ҏ员变量、方法以及构造函数进行注释,?@Qualifier 的标注对象是成员变量、方法入参、构造函数入参?/p>
@PostConstruct ?@PreDestroy:JSR-250 为初始化之后/销毁之前方法的指定定义了两个注释类Q这两个注释只能应用于方法上。标注了 @PostConstruct 注释的方法将在类实例化后调用Q而标注了 @PreDestroy 的方法将在类销毁之前调用?br />通过 <bean> 元素?init-method/destroy-method 属性进行配|,都只能ؓ Bean 指定一个初始化 / 销毁的Ҏ。但是?@PostConstruct ?@PreDestroy 注释却可以指定多个初始化 / 销毁方法,那些被标?@PostConstruct 或@PreDestroy 注释的方法都会在初始?/ 销毁时被执行?br />更多的关于注解用:L官方文档 4、ȝQ?br />1、注释配|不一定在先天上优?XML 配置。如?Bean 的依赖关pL固定的,Q如 Service 使用了哪几个 DAO c)Q这U配|信息不会在部v时发生调_那么注释配置优于 XML 配置Q反之如果这U依赖关pM在部|时发生调整QXML 配置昄又优于注释配|,因ؓ注释是对 Java 源代码的调整Q您需要重新改写源代码q新编译才可以实施调整?br />2、如?Bean 不是自己~写的类Q如 JdbcTemplate、SessionFactoryBean {)Q注释配|将无法实施Q此?XML 配置是唯一可用的方式?br />3、注释配|往往是类U别的,?XML 配置则可以表现得更加灉|。比如相比于 @Transaction 事务注释Q?aop/tx 命名I间的事务配|更加灵zd单?br />所以在实现应用中,我们往往需要同时用注释配|和 XML 配置Q对于类U别且不会发生变动的配置可以优先考虑注释配置Q而对于那些第三方cM及容易发生调整的配置则应优先考虑使用 XML 配置。Spring 会在具体实施 Bean 创徏?Bean 注入之前这两种配置方式的元信息融合在一赗?/p>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
配置了org.springframework.web.context.ContextLoaderListener后我们就不惜要编写代码显C地实例化ApplicationContext对象了。至于ؓ什么要使用监听是因为web.xml 的加载顺序是Qcontext-param -> listener -> filter -> servlet 。如果你是在不想使用监听Q或怽可以试下承struts2的org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter重写q个它的initҎ在StrutsPrepareAndExecuteFilterqo器init中实例化ApplicationContext对象加蝲配置信息Q虽然这U方法也可行Q但是当拦截每个action都会加蝲一ơ配|信息,重新实例化了一个新的web容器Q不仅浪费了资源也让spring更加依赖了struts?/p>
<package name="user" extends="struts-default">
<action name="login" class="userAction">
<result name="success">/success.jsp</result>
<result name="input" type="redirect">/index.jsp</result>
</action>
</package>
spring配置
<bean id="userDao" class="org.han.dao.impl.UserDaoImpl" />
<bean id="biz" class="org.han.service.impl.LoginBizImpl">
<property name="userdao" ref="userDao"/>
</bean>
<property name="biz" ref="biz" />
</bean>
注意U色部分Qstruts2的action class与对应的action bean必须相同,q样才能由spring理action;
当你导入了零配置插g包的时候千万要注意U定大于配置Q还是上面的spring配置Q只是不需要struts2配置了?br />W一U方式:只需要将Action的className对应到spring配置中的bean idp?br />@Action(value = "/login", results = { @Result(name = "success", location = "/success.jsp"),@Result(name="input",location="/index.jsp")},className="userAction")
public String login() throws Exception {
// TODO Auto-generated method stub
User u=biz.login(this.getUser());
if(u!=null){
return SUCCESS;
}
return INPUT;
}
W二U方式:
Action注解不需要className了,spring配置E作修改
<bean id="org.han.action.LoginAction" class="org.han.action.LoginAction" scope="prototype" >
<property name="biz" ref="biz" />
</bean>
q样可以是因为当你用零配置的时候,action的class默认是当前类的全cdQ所以和spring整合的时候刚好用全cd在spring配置中查找以全类名ؓid的bean?/p>
www.2cto.com
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="org.han.dao.impl,org.han.service.impl,org.han.action"/>
</beans>
@Namespace("/")
@Component(value="userLogin")
@Scope(value="prototype")
public class LoginAction extends ActionSupport {
public LoginAction() {
super();
// TODO Auto-generated constructor stub
System.out.println("action:"+this.hashCode());
}
@Autowired
private ILoginBiz biz;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Autowired
public void setBiz(ILoginBiz biz) {
this.biz = biz;
}
@Override
@Action(value = "hello", results = { @Result(name = "success", location = "/success.jsp"),@Result(name="input",location="/index.jsp")})
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println("biz:"+this.biz.hashCode());
User u=biz.login(this.getUser());
if(u!=null){
return SUCCESS;
}
return INPUT;
}
}
@Component 有一个可选的入参Q用于指?Bean 的名U。一般情况下QBean 都是 singleton 的,需要注?Bean 的地方仅需要通过 byType {略可以自动注入了Q所以大可不必指?Bean 的名U。除了提?@Component 注释外,q定义了几个拥有Ҏ语义的注释,它们分别是:@Repository、@Service ?@Controller。在目前?Spring 版本中,q?3 个注释和 @Component 是等效的Q但是从注释cȝ命名上,很容易看 3 个注释分别和持久层、业务层和控制层QWeb 层)相对应。虽然目前这 3 个注释和 @Component 相比没有什么新意,?Spring 在以后的版本中为它们添加特D的功能。所以,如果 Web 应用E序采用了经典的三层分层l构的话Q最好在持久层、业务层和控制层分别采用 @Repository、@Service ?@Controller 对分层中的类q行注释Q而用 @Component 寚w些比较中立的c进行注释?/p>
1. 使用Spring注解来注入属?span class="Apple-converted-space">
1.1. 使用注解以前我们是怎样注入属性的
cȝ实现Q?/p>public class UserManagerImpl implements UserManager {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
...
}
配置文gQ?/p><bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl">
<property name="userDao" ref="userDao" />
</bean>
<bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
1.2. 引入@Autowired注解Q不推荐使用Q徏议用@ResourceQ?span class="Apple-converted-space">
cȝ实现Q对成员变量q行标注Q?/p>public class UserManagerImpl implements UserManager {
@Autowired
private UserDao userDao;
...
}
或者(Ҏ法进行标注)public class UserManagerImpl implements UserManager {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
...
}
配置文g<bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl" />
<bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
@Autowired可以Ҏ员变量、方法和构造函数进行标注,来完成自动装配的工作。以上两U不同实现方式中Q@Autowired的标注位|不同,它们都会在Spring在初始化userManagerImplq个beanӞ自动装配userDaoq个属性,区别是:W一U实CQSpring会直接将UserDaocd的唯一一个bean赋值给userDaoq个成员变量Q第二种实现中,Spring会调用setUserDaoҎ来将UserDaocd的唯一一个bean装配到userDaoq个属性?span class="Apple-converted-space">
1.3. 让@Autowired工作h
要@Autowired能够工作Q还需要在配置文g中加入以下代?/p><bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
1.4. @Qualifier
@Autowired是根据类型进行自动装配的。在上面的例子中Q如果当Spring上下文中存在不止一个UserDaocd的beanӞ׃抛出BeanCreationException异常Q如果Spring上下文中不存在UserDaocd的beanQ也会抛出BeanCreationException异常。我们可以用@Qualifier配合@Autowired来解册些问题?span class="Apple-converted-space">
1. 可能存在多个UserDao实例 @Autowired
public void setUserDao(@Qualifier("userDao") UserDao userDao) {
this.userDao = userDao;
}
q样QSpring会找到id为userDao的beanq行装配?span class="Apple-converted-space">
2. 可能不存在UserDao实例 @Autowired(required = false)
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
1.5. @ResourceQJSR-250标准注解Q推荐用它来代替Spring专有的@Autowired注解Q?span class="Apple-converted-space">
Spring 不但支持自己定义的@Autowired注解Q还支持几个由JSR-250规范定义的注解,它们分别是@Resource、@PostConstruct以及@PreDestroy?span class="Apple-converted-space">
@Resource的作用相当于@AutowiredQ只不过@Autowired按byType自动注入Q而@Resource默认按byName自动注入|了。@Resource有两个属性是比较重要的,分别是name和typeQSpring@Resource注解的name属性解析ؓbean的名字,而type属性则解析为bean的类型。所以如果用name属性,则用byName的自动注入策略,而用type属性时则用byType自动注入{略。如果既不指定name也不指定type属性,q时通过反射机制使用byName自动注入{略?span class="Apple-converted-space">
@Resource装配序
1.6. @PostConstructQJSR-250Q?span class="Apple-converted-space">
在方法上加上注解@PostConstructQ这个方法就会在Bean初始化之后被Spring容器执行Q注QBean初始化包括,实例化BeanQƈ装配Bean的属性(依赖注入Q)?span class="Apple-converted-space">
它的一个典型的应用场景是,当你需要往Bean里注入一个其父类中定义的属性,而你又无法复写父cȝ属性或属性的setterҎӞ如:public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
private SessionFactory mySessionFacotry;
@Resource
public void setMySessionFacotry(SessionFactory sessionFacotry) {
this.mySessionFacotry = sessionFacotry;
}
@PostConstruct
public void injectSessionFactory() {
super.setSessionFactory(mySessionFacotry);
}
...
}
q里通过@PostConstructQؓUserDaoImpl的父c里定义的一个sessionFactoryU有属性,注入了我们自己定义的sessionFactoryQ父cȝsetSessionFactoryҎ为finalQ不可复写)Q之后我们就可以通过调用super.getSessionFactory()来访问该属性了?span class="Apple-converted-space">
1.7. @PreDestroyQJSR-250Q?span class="Apple-converted-space">
在方法上加上注解@PreDestroyQ这个方法就会在Bean初始化之后被Spring容器执行。由于我们当前还没有需要用到它的场景,q里不不LC。其用法同@PostConstruct?span class="Apple-converted-space">
1.8. 使用<context:annotation-config />化配|?span class="Apple-converted-space">
Spring2.1d了一个新的context的Schema命名I间Q该命名I间Ҏ释驱动、属性文件引入、加载期l入{功能提供了便捷的配|。我们知道注释本w是不会做Q何事情的Q它仅提供元数据信息。要使元数据信息真正起作用,必须让负责处理这些元数据的处理器工作h?span class="Apple-converted-space">
AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor是处理q些注释元数据的处理器。但是直接在Spring配置文g中定义这些Bean昑־比较W拙。Spring为我们提供了一U方便的注册q些BeanPostProcessor的方式,q就?lt;context:annotation-config />Q?/p><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config />
</beans>
<context:annotationconfig />隐式地向Spring容器注册AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor?PersistenceAnnotationBeanPostProcessor以及RequiredAnnotationBeanPostProcessorq?个BeanPostProcessor?span class="Apple-converted-space">
2. 使用Spring注解完成Bean的定?span class="Apple-converted-space">
以上我们介绍了通过@Autowired或@Resource来实现在Bean中自动注入的功能Q下面我们将介绍如何注解BeanQ从而从XML配置文g中完全移除Bean定义的配|?span class="Apple-converted-space">
2.1. @ComponentQ不推荐使用Q、@Repository、@Service、@Controller
只需要在对应的类上加上一个@Component注解Q就该cd义ؓ一个Bean了:@Component
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
...
}
使用@Component注解定义的BeanQ默认的名称QidQ是写开头的非限定类名。如q里定义的Bean名称是userDaoImpl。你也可以指定Bean的名Uͼ
@Component("userDao")
@Component是所有受Spring理lg的通用形式QSpringq提供了更加l化的注解Ş式:@Repository、@Service、@ControllerQ它们分别对应存储层BeanQ业务层BeanQ和展示层Bean。目前版本(2.5Q中Q这些注解与@Component的语义是一LQ完全通用Q在Spring以后的版本中可能会给它们q加更多的语义。所以,我们推荐使用@Repository、@Service、@Controller来替代@Component?span class="Apple-converted-space">
2.2. 使用<context:component-scan />让Bean定义注解工作h<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com.kedacom.ksoa" />
</beans>
q里Q所有通过<bean>元素定义Bean的配|内容已l被U除Q仅需要添加一?lt;context:component-scan />配置px有问题了——Spring XML配置文g得到了极致的化(当然配置元数据还是需要的Q只不过以注释Ş式存在Ş了)?lt;context:component-scan />的base-package属性指定了需要扫描的cdQ类包及光归子包中所有的c都会被处理?span class="Apple-converted-space">
<context:component-scan />q允许定义过滤器基包下的某些类U_或排除。Spring支持以下4U类型的qo方式Q?/p>
以正则表辑ּZQ我列D一个应用实例: <context:component-scan base-package="com.casheen.spring.annotation">
<context:exclude-filter type="regex" expression="com\.casheen\.spring\.annotation\.web\..*" />
</context:component-scan>
值得注意的是<context:component-scan />配置不但启用了对类包进行扫描以实施注释驱动Bean定义的功能,同时q启用了注释驱动自动注入的功能(卌隐式地在内部注册了AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessorQ,因此当?lt;context:component-scan />后,可以将<context:annotation-config />U除了?span class="Apple-converted-space">
2.3. 使用@Scope来定义Bean的作用范?span class="Apple-converted-space">
在用XML定义BeanӞ我们可能q需要通过bean的scope属性来定义一个Bean的作用范_我们同样可以通过@Scope注解来完成这工作:@Scope("session")
@Component()
public class UserSessionBean implements Serializable {
...
}
3. 参?span class="Apple-converted-space">
http://kingtai168.iteye.com/blog/244002
http://www.iteye.com/topic/244153
http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config
http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-classpath-scanning
]]>
]]>
警告: No configuration found for the specified action: '/myNameSpace/login.action' in namespace: ''. Form action defaulting to 'action' attribute's literal value.
struts.xml配置信息Q部分)
<package name="packageName" extends="struts-default" namespace="/myNameSpace">
<action name="login" class="com.jato.srvclink.test.login.LoginAction" method="login">
jsp面配置信息Q部分)
<s:form action="/myNameSpace/login.action">
思考:没有?/span>''?/span>namespace中发现指定的action '/myNameSpace/login.action'
{疑Q因为配|的struts2标签q未指定namespace属性。所?/span>struts2会默认从根命名空?/span>"/"搜烦action?/span>' /myNameSpace/login.action'Q如果搜索不到将q入默认命名I间''搜烦actionhԌ在默认命名空间中是肯定找不到我们 定义?/span>action的,所以,struts2抛出一个警告信息?/span>
但是Z么我们没有填?/span>namespaceQ我们的h也可以正常访问呢Q?/span>
我们来看一下解析后?/span>html
查看源码得到?/span>htmlQ部分)
<form id="login" onsubmit="return true;" action="/srvclink/myNameSpace/login.action" method="post">
我们看到form提交?/span>action串是准确?/span>urlhQ?/span>action串确实是/srvclinQ应用根Q?/span>/myNameSpaceQ命名空_/login.action?/span>
命名I间中找不到action定义Qƈ不意味着q个action真的不存在,只是我们的代码有问题而已。还有一Ҏ我们?/span>jsp面?/span>actionh?/span> 手动的加入了.action后缀。事实上struts2会自动追?/span>.action的,因ؓ我们q没有合法的使用struts2的标{,所?/span>struts2 q里q没有给我们q加.actionQ解析后的代码中存在?/span>.actionQ完全是我们手动?/span>jsp面填写的,有疑问的|友可以不手动添加查?/span> html?/span>
我们修改我们的程序代?/span>
jsp面配置信息Q部分)修改后加?/span>namespace属性,修改action属性gؓ/login.action
<s:form action="/login.action" namespace="/myNameSpace">
h面后,大家很失望吧Q警告依然存在。但是我们看一下警告信息?/span>
警告信息Q?/span>
警告: No configuration found for the specified action: '/login.action' in namespace: '/myNameSpace'. Form action defaulting to 'action' attribute's literal value.
没有?/span>'/myNameSpace'?/span>namespace中发现指定的action '/login.action'
毫无疑问Q这里的警告和第一ơ的警告信息截然不同。我们现在存在命名空_'/myNameSpace'能够?/span>struts2索到Qƈ不是开始的''。那问题的关键在哪里呢?
?/span>namespace中没有发现指定的action '/login.action' Q?Q?/span>
我们来看一?/span>struts.xml中的配置Q?/span>
struts.xml配置信息Q部分)
<package name="packageName" extends="struts-default" namespace="/myNameSpace">
<action name="login" class="com.jato.srvclink.test.login.LoginAction" method="login">
是的Q我?/span>'/myNameSpace'命名I间下,只有action名字?/span>'login'的定义,q没有所谓的'/login.action' 定义Q所?/span>struts2的警告ƈ未错。如果大家对q个抱有怀疑,可以修改action的名?/span>'login'?/span>‘/longin.action’
<action name="/login.action" class="com.jato.srvclink.test.login.LoginAction" method="login">
h面时你会发C在报警告信息Q原因很单。因为在命名I间?/span>'myNameSpace'下确实存在命名ؓ'/login.action'?/span>action?/span>
我们再次修改配置文g
jsp面配置信息Q部分)修改?/span>action属性gؓlongin
<s:form action="login" namespace="/myNameSpace">
h面Ӟ我们发现不再有警告信息了?/span>
如果你有_l心Q我想你应该可以d的明白ؓ什?/span>struts2会报警了吧?你也应该明白了?/span>struts2标签action中添?/span>/U后h反而报错的原因了?/span>
实现Q?br /> W一步:创徏一个Web工程
在MyEclipseQ通过菜单File->New->Web ProjectQ在Project Name输入工程名称Strut2TravelQ点解确定完成创Z个工E?br /> 注:MyEclipse属于一个IDEl承开发环境,可以快速的创徏Web目。读者可以手工创建,只需满目的文件结构即可。其中WEB-INF文g夹必不可?/p>
W二步:导入Struts2的核心支持包
commons-fileupload-1.2.1.jar
commons-io-1.3.2.jar
commons-logging-1.0.4.jar
freemarker-2.3.15.jar
ognl-2.7.3.jar
struts2-core-2.1.8.1.jar
xwork-core-2.1.6.jar
注:Struts2有大量的jar包,支持大量的功能,不同cd的应用可能需要不同的包支持。以上的5个包为Struts2的核心包Q用Struts2必须使用?/p>
W三步:配置struts2转发qo?/span> W四?/span>Q创入页面login.jsp、结果页面welcome.jsp和error.jsp W五?/span>Q创建Action文gLoginAction和struts2.xml文g import com.opensymphony.xwork2.ActionSupport; public class LoginAction extends ActionSupport{ W五步:程序发布到TomcatQ启动Tomcat卛_?br /> 通过本实例读者应该掌握如何配|ƈ~写一个最单最基本的应用,对于初学读者以了解ZQ没必要q一些问题?/p>
~辑web.xml文gQ添加以下内?br /> <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>
注:“/*”表示涉及本工E的所有浏览器端的h都经qstruts2qo器处理?/p>
login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="GB2312"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head><title>d界面</title></head>
<body>
<form action="LoginAction.action">
用户名:<input name="username"><br>
?码:<input type="password" name="userpass"><br>
<input type="submit" value="??>
<input type="reset" value="??>
</form>
</body>
</html>
welcome.jsp
<%@ page language="java" import="java.util.*" pageEncoding="GB2312"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Ƣ迎</title>
</head>
<body>
<font color="red" size="10">d成功Q?lt;/font>
</body>
</html>
error.jsp
<%@ page language="java" import="java.util.*" pageEncoding="GB2312"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
</head>
<body>
<font color="red" size="10">用户或密码错误!</font>
</body>
</html>
注:本实例是最单的应用Q以上ؓUJSP文gQStruts2提供大量使用的标{,本书后面的实例会使用到?/p>
LoginAction.java
package com;
private String username;
private String userpass;
public String execute(){
if("daniel".equals(username)&&"abcde".equals(userpass))
return SUCCESS;
else
return ERROR;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpass() {
return userpass;
}
public void setUserpass(String userpass) {
this.userpass = userpass;
}
}
注:默认配置情况下执行execute()ҎQ实际应用中l常更改配置。本书后面将深入讲解。注意本cM的username和userpass必须和网|件的name属性名一致?br />struts.xml
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="struts2demo" extends="struts-default">
<action name="loginAction" class="com.LoginAction">
<result name="success">/welcome.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
</struts>
开发工PMyEclipse6
Web服务器:Tomcat6
Struts版本Q?/span>Struts2.0.11.1
JDK版本Q?/span>JDK1.5.0_12
J2EE版本Q?/span>Java EE5.0
在本pd教程?/span>Web工程的上下文路径都是struts2Q如果在Web根目录有一?/span>index.jsp文gQ则讉K路径如下Q?/span>
http://localhost:8080/struts2/index.jsp
׃MyEclipse6目前q不支持Struts2Q所以我们需要到struts.apache.orgM?/span>Struts2安装包。要x怋?/span>Struts2Q至需要如下五个包Q可能会因ؓStruts2的版本不同,包名略有差异Q但包名的前半部是一LQ?/span>
struts2-core-2.0.11.1.jar
xwork-2.0.4.jar
commons-logging-1.0.4.jar
freemarker-2.3.8.jar
ognl-2.6.11.jar
Struts2虽然在大版本号上是第二个版本Q但基本上在配置和用上已经完全颠覆?/span>Struts1.x的方式(当然Q?/span>Struts2仍然是基?/span>MVC模式的,也是动作驱动的,可能q是唯一没变的东西)?/span>Struts2实际上是?/span>Webwork基础上构v来的MVC框架。我们从Struts2的源代码中可以看刎ͼ有很多都是直接用的xwork(Webwork的核心技?/span>)的包。既然从技术上来说Struts2是全新的框架Q那么就让我们来学习一下这个新的框架的使用Ҏ?/span>
如果大家使用q?/span>Struts1.xQ应该对建立ZStruts1.x?/span>WebE序的基本步骤非常清楚。让我们先来回顾一下徏立基?/span>Struts1.x?/span>WebE序的基本步骤?/span>
1. 安装Struts。由?/span>Struts的入口点?/span>ActionServletQ所以得?/span>web.xml中配|一下这?/span>Servlet?/span>
2. ~写Actionc(一般从org.apache.struts.action.Actioncȝ承)?/span>
3. ~写ActionFormc(一般从org.apache.struts.action.ActionFormcȝ承)Q这一步不是必ȝQ如果要接收客户端提交的数据Q需要执行这一步?/span>
4. ?/span>struts-config.xml文g中配|?/span>Action?/span>ActionForm?/span>
5. 如果?/span>采集用户录入的数据,一般需要编写若q?/span>JSP面Qƈ通过q些JSP面中的form数据提交给Action?/span>
下面我们按着~写struts1.xE序?/span>q五步和struts2.xE序的编写过E一一对应Q看看它们谁?#8220;?#8221;。下面我们来~写一个基?/span>Struts2?/span>WebE序。这个程序的功能是让用户录入两个整数Qƈ提交l一?/span>Struts ActionQƈ计算q两个数的代数和Q如果代码和为非负数Q则跌{?/span>positive.jsp面Q否则蟩转到negative.jsp面?br />
【第1步?/span> 安装Struts2
q一步对?/span>Struts1.x?/span>Struts2都是必须的,只是安装的方法不同?/span>Struts1的入口点是一?/span>ServletQ?/span>Struts2的入口点是一个过滤器(Filter)。因此,Struts2要按qo器的方式配置。下面是?/span>web.xml中配|?/span>Struts2的代码:
【第2步?/span> ~写Actionc?/span>
q一步和Struts1.x也必进行。只?/span>Struts1.x中的动作cdMActioncMl承Q?/span>Struts2.x的动作类需要从com.opensymphony.xwork2.ActionSupportcȝѝ下面是计算两个整数代码和的Actionc,代码如下Q?/span>从上面的代码可以看出Q动作类的一个特征就是要覆盖executeҎQ只?/span>Struts2?/span>executeҎ没有参数了,?/span>Struts1.x?/span>executeҎ有四个参数。而且executeҎ的返回g不同的?/span>Struts2只返回一?/span>StringQ用于表q执行结果(是一个标志)。上面代码的其他部分在下面讲解?/span>
【第3步?/span> ~写ActionFormc?/span>
在本例中当然需要?/span>ActionForm了。在Struts1.x中,必须要单独徏立一?/span>ActionFormc(或是定义一个动?/span>FormQ,而在Struts2?/span>ActionForm?/span>Action已经二合一了。从W二步的代码可以看出Q后面的部分是应该写在ActionFormcM的内宏V所以在W?/span>2步,本例?/span>ActionFormcdl编写完成(是Actioncȝ后半部分Q?/span>
【第4步?/span> 配置Actionc?/span>
q一?/span>struts1.x?/span>struts2.x都是必须的,只是?/span>struts1.x中的配置文g一般叫struts-config.xmlQ当然也可以是其他的文g名)Q而且一般放?/span>WEB-INF目录中。而在struts2.x中的配置文g一般ؓstruts.xmlQ放?/span>WEB-INF"classes目录中。下面是?/span>struts.xml中配|动作类的代码:?/span><struts>标签中可以有多个<package>Q第一?/span><package>可以指定一?/span>Servlet讉K路径Q不包括动作名)Q如“/mystruts”?/span>extends属性承一个默认的配置文g“struts-default”Q一般都l承于它Q大家可以先不去它?/span><action>标签中的name属性表C动作名Q?/span>class表示动作cd?/span>
<result>标签?/span>name实际上就?/span>executeҎq回的字W串Q如果返回的?#8220;positive”Q就跌{?/span>positive.jsp面Q如果是“negative”Q就跌{?/span>negative.jsp面。在<struts>中可以有多个<package>Q在<package>中可以有多个<action>。我们可以用如下?/span>URL来访问这个动作:
http://localhost:8080/struts2/mystruts/sum.action
?/span>Q?/span>Struts1.x的动作一般都?/span>.dol尾Q?/span>Struts2是以.actionl尾?/span>
【第5步?/span> ~写用户录入接口Q?/span>JSP面Q?/span>
1. ȝ面(sum.jspQ?/span>
?/span>Web根目录徏立一?/span>sum.jspQ代码如下:
?/span>sum.jsp中用了Struts2带的tag。在Struts2中已l将Struts1.x的好几个标签库都l一了,?/span>Struts2中只有一个标{ֺ/struts-tags。这里面包含了所有的Struts2标签。但使用Struts2的标{֤家要注意一下。在<s:form>中最好都使用Struts2标签Q尽量不要用HTML或普通文本,大家可以?/span>sum.jsp的代码改为如下的形式Q看看会出现什么效果:
... ...
求代数和
<br/>
<s:form action="mystruts/sum.action" >
操作?/span>1Q?/span><s:textfield name="operand1" /><br/>
操作?/span>2Q?/span><s:textfield name="operand1" /><br/>
<s:submit value="代数?/span>" />
</s:form>
... ...
提示一下,?/span><s:form>?/span>Struts2使用<table>定位?/span>
2. positive.jsp
3. negative.jsp
q两?/span>jsp面的实C码基本一P只用了一?/span><s:property>标签来显C?/span>ActioncM?/span>sum属性倹{?/span><s:property>标签是从request对象中获得了一个对象中得到?/span>sum属性,如我们可以用如下的代码来代?/span><s:property value=”sum”/>Q?/span>
?
?
值栈(ValueStack)
Struts2?/span>OGNL上下文设|ؓStruts2中的ActionContext(内部使用的仍然是OgnlContext)Qƈ值栈设ؓOGNL的根对象?/span>
我们知道Q?/span>OGNL上下文中的根对象可以直接讉KQ不需要用Q何特D的“标记”Q而引用上下文中的其他对象则需要?#8220;#”来标记。由于值栈是上下文中的根对象,因此可以直接讉K。那么对于值栈中的对象该如何访问呢Q?/span>Struts2提供了一个特D的OGNLPropertyAccessorQ它可以自动查找栈内的所有对?/span>(从栈到栈底)Q直接找C个具有你所查找的属性的对象。也是_对于值栈中的M对象都可以直接访问,而不需要?#8220;#”?/span>
假设值栈中有两个对象Q?/span>student?/span>employeeQ两个对象都?/span>name属性,student有学号属?/span>numberQ?/span>employee有薪水属?/span>salary?/span>employee先入栈,student后入栈,位于栈顶Q那么对于表辑ּname,讉K的就?/span>student?/span>name属性,因ؓstudent对象位于栈顶Q表辑ּsalaryQ访问的是employee?/span>salary属性。正如你所见,讉K值栈中的对象属性或ҎQ无L明对象,也不?#8220;#”Q就好像值栈中的对象都是OGNL上下文中的根对象一栗这是Struts2?/span>OGNL基础上做出的改进?/span>
值栈中的Action实例
Struts2框架L?/span>Action实例攑֜栈顶。因?/span>Action在值栈中,而值栈又是OGNL中的根,所以引?/span>Action的属性可以省?#8220;#”标记Q这也是Z么我们在l果面中可以直接访?/span>Action的属性的原因?/span>
Struts2中的命名对象
Struts2q提供了一些命名对象,q些对象没有保存在值栈中,而是保存?/span>ActionContext中,因此讉Kq些对象需要?#8220;#”标记。这些命名对象都?/span>Mapcd?/span>
parameters
用于讉Kh参数。如Q?/span>#parameters['id']?/span>#parameters.idQ相当于调用?/span>HttpServletRequest对象?/span>getParameter()Ҏ?/span>
注意Q?/span>parameters本质上是一个?/span>HttpServletRequest对象中的h参数构造的Map对象Q一量对象被创徏(在调?/span>Action实例之前已l创建好?/span>)Q它?/span>HttpServletRequest对象没有了M关系?/span>
request
用于讉Kh属性。如Q?/span>#request['user']?/span>#request.userQ相当于调用?/span>HttpServletRequest对象?/span>getAttribute()Ҏ?/span>
session
用于讉Ksession属性。如Q?/span>#session['user']?/span>#session.userQ相当于调用?/span>HttpSession对象?/span>getAttribute()Ҏ?/span>
application
用于讉Kapplication属性。如Q?/span>#application['user']?/span>#application.userQ相当于调用?/span>ServletContext?/span>getAttribute()Ҏ?/span>
attr
如果PageContext可用Q则讉KPageContextQ否则依ơ搜?/span>request?/span>session?/span>application对象?br />
假设你的ActioncM有变量String password; 要想获取面中传q来的passwordQ必Mؓpassword讄get 和set Ҏ。当你的面q入ActionӞActionContextQAction上下文)通过setҎ获取password的值ƈ压入值栈栈顶Q同时request也获取到password的|同时也如堆栈Qsession{对象的g被压入堆栈,ActionContext中的值在面中可以直接用<s:porperty value="password">取值显C,而request中存储的password通过<s:porperty value="#request.password">或?{password}取倹{即struts是通过一个值栈来存储所有对象和ActionContext中的值得。ActionContext为栈对象,也称跟对象,ActionContext的值可以直接用变量名取Q而其他的变量需要用#变量名取倹{?/pre>
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation">
<value>classpath:SqlMapConfig.xml</value>
</property>
<property name="dataSource">
<ref bean="dataSource"/>
</property>
< /bean>
中的
<value>classpath:SqlMapConfig.xml</value>
然后把SqlMapConfig.xml攑ֈsrc下面