《跟我一起做J2EE版Blog–jPress》6(Spring集成Struts2,打通第一个Action)
连载第六集,前面讲了Spring和Hibernate的集成,集成的方法主要是Spring中配置好datasource和SessionFactory的bean,在Dao中注入sessionFactory对数据库进行操作。
这一讲来集成Spring和Struts,并且打通第一个action,在action中使用hibernate并返回JSP。Struts框架的作用是将项目的逻辑层和视图层分离出来,实现MVC。Struts可以减少jsp文件,因为JSP这玩意儿的存在将视图和逻辑混杂到令人发指的程度,所以我是坚决不会在JSP页面中写任何JAVA语句的(顺便说一句,jPress项目甚至不准备写任何JSP文件,视图层用Freemarker设计,这个模板引擎太强大了,可以说使用Struts不配合上Freemarker那就是糟蹋东西了)。Spring和Struts这二者的集成方式主要靠编辑web.xml文件。我们需要在web.xml中添加几个监听器和过滤器,并且从marven中央库中引入一个struts2-spring-plugin的jar包。下面是个插件包的marven描述:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.3.1.2</version>
</dependency>
接下来编辑web.xml,添加监听器和过滤器:
启动Tomcat或者Resin,我个人比较喜欢在项目开发阶段使用Resin不断调试,因为Resin是最快的JAVA WEB容器,效率很高;在服务器部署的时候使用Tomcat,因为Tomcat性能稳定,可以作为操作系统的service,并且可以通过配置NIO模式、GZip模式等提高Tomcat的各项性能。
浏览器中输入http://localhost:8080/jPress/hello,这时候WEB容器判断出hello是一个action名,于是将请求转发到TestAction并寻找其中的excute方法,spring会适时地介入并提供一个userDao注入给action使用,这个userDao在WEB容器启动时已经定义好了,是一个UserDaoImpl的对象,其中使用的sessionFactory也是Spring为他提供的。action执行OK后根据逻辑会返回SUCCESS或者ERROR,根据Struts中的定义,如果返回SUCCESS则内部跳转到index.jsp,在index.jsp中我们使用struts标签就能看到处理结果了。
正如我所说,今天只是打通WEB容器与SSH三者之间呃脉络,测试成功后我们会抛弃JSP的,因为我太喜欢Freemarker了。打通脉络后,下一章我们将先暂停JAVA端的开发,先跟着我去Dreamweaver和Photoshop上去设计DIV+CSS,我们要为jPress设计第一套默认皮肤,然后将默认皮肤转化成模板ftl文件。
这一讲来集成Spring和Struts,并且打通第一个action,在action中使用hibernate并返回JSP。Struts框架的作用是将项目的逻辑层和视图层分离出来,实现MVC。Struts可以减少jsp文件,因为JSP这玩意儿的存在将视图和逻辑混杂到令人发指的程度,所以我是坚决不会在JSP页面中写任何JAVA语句的(顺便说一句,jPress项目甚至不准备写任何JSP文件,视图层用Freemarker设计,这个模板引擎太强大了,可以说使用Struts不配合上Freemarker那就是糟蹋东西了)。Spring和Struts这二者的集成方式主要靠编辑web.xml文件。我们需要在web.xml中添加几个监听器和过滤器,并且从marven中央库中引入一个struts2-spring-plugin的jar包。下面是个插件包的marven描述:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.3.1.2</version>
</dependency>
接下来编辑web.xml,添加监听器和过滤器:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name>jpress</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <context-param> <description>指定Spring的bean配置文件</description> <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> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>openSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>openSessionInViewFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <!-- define a JspSupportServlet Object --> <servlet-name>JspSupportServlet</servlet-name> <servlet-class>org.apache.struts2.views.JspSupportServlet</servlet-class> <!-- setting JspSupportServlet auto start --> <load-on-startup>1</load-on-startup> </servlet> </web-app>这样jPress就具有Struts的能力了,通过web.xml中监听器和触发器的配置,我们能够在struts的action中使用spring容器中的bean。在MyEclipse中为项目添加Struts特性后,会得到一个struts.xml的配置文件,下面我们来配置一个测试action,在这个测试action中我们调用数据层的方法,数据操作结束后,返回信息给JSP。首先编写struts.xml,如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <constant name="struts.devMode" value="true" /> <constant name="struts.custom.i18n.resources" value="com.flyding.jpress.messages"/> <package name="default" namespace="/" extends="struts-default"> <default-action-ref name="hello"></default-action-ref> <global-results> <result name="error" type="freemarker">/WEB-INF/views/error.ftl</result> </global-results> <action name="hello" class="com.flyding.jpress.actions.TestAction"> <result> /index.jsp </result> </action> </package> </struts>这段配置文件做了一个名叫hello的action路由,当用户在浏览器中访问/hello这个地址时会被struts截取,struts会将请求发送到配置好的com.flyding.jpress.actions.TestAction这个类中,并寻找execute这个方法,根据execute方法返回的字符串判断这次请求继续往哪儿流,如果execute返回SUCCESS,则往index.jsp流,如果execute返回ERROR,则往/WEB-INF/views/error.ftl这个模板文件流,模板文件我们下一章再讲,今天先讲以JSP返回显示信息的方法。下面是TestAction的JAVA文件:
public class TestAction extends ActionSupport { private static final long serialVersionUID = 5425386805840506298L; //@Autowired //private LinkDao linkDao; @Autowired private UserDao userDao; User user; String exception; @Override public String execute() { try { userDao.changePassword((long)1, "8215085", "8215083"); } catch (UserNoMatch e) { this.exception=e.getMessage(); return ERROR; } return SUCCESS; } public User getUser(){ return this.user; } public String getException(){ return this.exception; } }在Action中,我们用@Autowired注解标明这个UserDao类型的userDao变量是需要Spring给我们自动注入的,虽然。。。虽然有一些说法说是不建议在属性定义的时候autowire,而是应该在public get方法上进行织入,但是我个人还是比较习惯直接织入的,可以省去很多getter&setter,性能上应该没有什么差异。同时我们需要回到上一讲的UserDaoImpl类中,在这个类开头部分使用@Component("userDao")注解标明这个类将作为一个名叫userDao的组件保存进Spring容器中供上层逻辑调用。Action中的execute方法调用了UserDao的修改密码方法,这个方法需要用户ID,原始密码,新密码三个参数,如果ID跟原始密码错误则抛出验证失败的异常,这种做法也是我个人比较提倡的做法,采用自定义异常的方法取代项目逻辑中if else以及switch等语句,这将提高项目的代码质量。
启动Tomcat或者Resin,我个人比较喜欢在项目开发阶段使用Resin不断调试,因为Resin是最快的JAVA WEB容器,效率很高;在服务器部署的时候使用Tomcat,因为Tomcat性能稳定,可以作为操作系统的service,并且可以通过配置NIO模式、GZip模式等提高Tomcat的各项性能。
浏览器中输入http://localhost:8080/jPress/hello,这时候WEB容器判断出hello是一个action名,于是将请求转发到TestAction并寻找其中的excute方法,spring会适时地介入并提供一个userDao注入给action使用,这个userDao在WEB容器启动时已经定义好了,是一个UserDaoImpl的对象,其中使用的sessionFactory也是Spring为他提供的。action执行OK后根据逻辑会返回SUCCESS或者ERROR,根据Struts中的定义,如果返回SUCCESS则内部跳转到index.jsp,在index.jsp中我们使用struts标签就能看到处理结果了。
正如我所说,今天只是打通WEB容器与SSH三者之间呃脉络,测试成功后我们会抛弃JSP的,因为我太喜欢Freemarker了。打通脉络后,下一章我们将先暂停JAVA端的开发,先跟着我去Dreamweaver和Photoshop上去设计DIV+CSS,我们要为jPress设计第一套默认皮肤,然后将默认皮肤转化成模板ftl文件。