SSH有了,现在我们要把我们的struts层从原来的1.3替换成struts2.x,引入了struts2.0后我们会发觉我们的代码和框架的变化还是不小的
1)在struts2的方法里,一切变量是线程安全的,而原有的struts1不是的;
2)在struts2中如果你声明了如下这样的代码:
privater String studentName=””; public void setStudentName(String studentName){ this.studentName = studentName; } public String getStudentName(){ return this.studentName; } |
那么当你对这个studentName进行符值后,不需要再把它用request.setAttribute这样的形式把值带到页面中去了,相当于你可以省去在request中来回的setAttribute{…}getAttribute{…}的操作(有时由于忘记把一个listset到request中去,经常导致一个页面就是不显示列表,对吧?这样的事可以被极大程度上避免掉)。
3)更丰富且描述简单的页面标签,可以直接支持将一个Object和页面的进行绑定,如:
我在后台如果有一个StudentVO,这个StudentVO如下描述:
private String studentNo = ""; private String studentName = "";
public String getStudentNo() { return studentNo; }
public void setStudentNo(String studentNo) { this.studentNo = studentNo; }
public String getStudentName() { return studentName; }
public void setStudentName(String studentName) { this.studentName = studentName; } |
于是我在前台jsp里可以直接这样使用我的标签和我这个VO中的某个字段进行绑定:
4)原有在struts1中的formbean彻底消失,去而代之的是使用VO对象,一个strutsaction就是一个普通的类,只是它extendsActionSupport而己。
5)良好的注入机制,连session,request, response都可以注入了,因此你的一个action方法就是一个普通类方法,这样做的好处是极大化将servlet与我们的action进行解耦合。试想如果是原有的struts1的action方法,我现在要改成swing的actionPerform,你是不是要把原有的action方法包括传参都要进行重构啊?而现在有了struts2,由于连session,request, response都是被注入的,因此这个struts2的action方法可以直接重用。
Strtus2还有很多好处,这边不一一列举了,在struts2的官方文档和stepby step等书中详细有说,我们这边主要以实战为主,讲述struts2怎么和spring进行整合并且能够开发我们的应用。
我们还是用我们的Maven2。
Struts2变化很大,它是一个几乎被重写的框架,而不是一个“增强”的框架,它是继承自xwrok的框架并且在整个框架中全面使用了filter机制。
对于我们的maven的pom.xml文件来说,这个lib库的改动还是很大的。
甚至还会出现一些莫名奇妙的错误而其原因是因为lib库的版本不对或者是有冲突,为此笔者整理了一份ssh2的所有需要的jar的mavenpom.xml文件。
虽然,我会在后面把这个xml文件完整列出来但还是希望大家在一开始跟着我能够一步步走,对pom.xml文件和工程进行排错,这样你将对一些常用的框架的lib库有个比较熟悉的过程。
我们新建一个maven的web工程-myssh2,并将原有的myssh工程中的pom.xml文件拷入工程中。
请确保你使用的jdk版本为version1.6.x。
打开这个pom.xml文件,把下面这段所有的关于struts1.3的依赖包全部去除。
|
我们把原有的struts1.3的依赖包去除后加入struts2的依赖包
|
存盘后,此时maveneclipse插件会自动开始编译和下载相关的jar到你的本地maven的repository中,然后我们会发觉这个pom.xml文件出错了:
抛一个sun.tool.jar没有找到的错误。
道理很简单,因为该tool.jar其实已经存在在我们本地安装的jdk的lib目录下了,因此我们不需要这个包,但是maven是自动依赖的,你没有看到它在pom.xml文件中出现不代表这层依赖关系不存在。
因此我们需要做的是exclude这个包。
让我们在maveneclipse插件中打开这个pom.xml文件,切换到“DependencyHierarchy”视图,然后找到这个tool.jar文件,点左边这个list中的tools:1.5.0然后右键选“ExcludeMaven Artifact”。
选[ok]按钮然后存盘。
我们可以看到这个pom.xml文件一切正常了,没有红色的“叉叉”了,我们切换到pom.xml视图,可以看到它其实做了这么一件事(注意红色标粗的语句):
|
然后:
1)我们把原先ssh工程中的resources目录下所有的东西拷到myssh2工程的resources目录下;
2)我们把原先的ssh工程的java文件拷过来;
3)我们把原先的ssh工程的src/main/webapp目录下的文件也拷贝过来;
4)不要忘了把WEB-INF/web.xml文件和index.jsp文件也拷过来啊!
1)我们把原有的org.sky.ssh.student.form和org.sky.ssh.login.form删了;
2)我们把原有的service类中的一些需要传入StudentForm的方法的中的StudentForm改成
org.sky.ssh.vo.StudentVO,其内容如下:
package org.sky.ssh.vo;
import java.io.Serializable;
public class StudentVO implements Serializable { private String studentNo = ""; private String studentName = "";
public String getStudentNo() { return studentNo; }
public void setStudentNo(String studentNo) { this.studentNo = studentNo; }
public String getStudentName() { return studentName; }
public void setStudentName(String studentName) { this.studentName = studentName; } } |
3)把原有的两个action文件也删了吧(删了就删了,反正我们要用struts2来重写)
4)打开web.xml文件,把下面这些内容去掉
|
5)打开web.xml文件,把.do都改成.action
6)打开web.xml文件,把这些去掉
/WEB-INF/struts-config/login.xml, /WEB-INF/struts-config/index.xml
|
7)打开web.xml文件,加入struts2的配置
|
可以看到struts2框架是一个基于filter的框架,确保这个filter在所有工程中你自己定义的filter的最后面,要不然你自己定义的filter会被struts2给filter掉(这点一定要注意)。
最后别忘了把:
/login.action
|
这边的原有的/login.do改成/login.action哦。
确保工程编译没有任何问题,然后我们按照番外篇《第十九天》中的“四、如何让Maven构建的工程在eclipse里跑起来”对工程进行设置,使得工程可以在eclipse的tomcat中跑起来。
就是下面这个狗屁错。
其原因在于由于使用的struts2。原有的这个cglib:2.1.3,这个包对于spring3和hibernate3还有struts1.3来说没有任何问题,在遇到struts2时就冲突了,因此我们需要把这个包也给exclude掉
Exclude掉了后没有cglib包了,AOP类反射没法玩了,怎么办?
简单:
手工在pom.xml文件中添加一个cglib较新版本的包,如下:
|
再运行工程,一切无误,tomcat启动时正常,说明我们的框架已经搭好了,接下来我们就要开始改我们的struts的action层了。
Struts2只有一个核心的struts.xml文件,它应该放在运行工程的classpath路径下即WEB-INF/classes目录下,所以我们把它放在工程的resources目录下,使得它在工程被编译时会被自动编译到工程的WEB-INF/classes目录下.
其内容如下:
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
/ indexInit
method="indexInit">
method="popAddStudent">
method="addStudent">
method="addStudent">
method="delStudent"> / indexInit
|
struts2中的action就是一个普通的class,它的public方法名就是一个具体的action,这相当于原有struts1中的DispatchAction,只不过它做的更加灵活。
如:我有一个按钮叫addStudent,如果你在你的action的类中有一个publicString addStudent()方法,那么你的这个按钮对应的action名就叫/addStudent.action(神奇吧)。
我们对应着“
package org.sky.ssh.login.action; import java.util.Map; import javax.annotation.Resource; import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts2.interceptor.ServletRequestAware; import org.apache.struts2.interceptor.ServletResponseAware; import org.apache.struts2.interceptor.SessionAware; import org.sky.ssh.service.LoginService; import org.sky.ssh.util.Constants; import org.sky.ssh.util.session.UserSessionInfo; import com.opensymphony.xwork2.ActionSupport; public class LoginAction extends ActionSupport implements SessionAware, ServletRequestAware, ServletResponseAware { protected final Log logger = LogFactory.getLog(getClass()); private Map att; private HttpServletRequest request = null; private HttpServletResponse response; @Resource LoginService loginService; public void setServletRequest(HttpServletRequest request) { this.request = request; } public void setServletResponse(HttpServletResponse response) { this.response = response; } public void setSession(Map att) { this.att = att; } public String execute() throws Exception { String loginId = ""; String loginPwd = ""; HttpSession session = request.getSession(); String loginCode = "100"; try { loginId = (String) request.getParameter("loginId"); loginPwd = (String) request.getParameter("loginPwd"); if (loginService.login(loginId, loginPwd)) { UserSessionInfo uinfo = new UserSessionInfo(); uinfo.setLoginId(loginId); session.setAttribute(Constants.USER_SESSION, uinfo); } else { loginCode = "101"; } request.setAttribute("loginCode", loginCode); if (!loginCode.equals("100")) { RequestDispatcher dispatcher = request.getRequestDispatcher("/jsp/login/login.jsp"); dispatcher.forward(request, response); } return SUCCESS; } catch (Exception e) { logger.error("UserLogin Exception:" + e.getMessage(), e); throw new Exception("UserLogin Exception:" + e.getMessage(), e); } } } |
在查看此类时注意以下几点地方:
1)注意request, response, session是怎么被应用到struts2的action的class中去的;
2)public String execute() throws Exception {…}方法就相当于原有struts1.x中的unspecified方法,是被默认执行的;
3)action方法必须返回一个String类型,默认有SUCCESS和FAIL(注意大小写),它就对应着你的struts.xml文件中的:
/ indexInit
|
注意这个type=”redirectAction”,它只是说明这个跳转是一个redirect,不管你在上一个action的request中setAttribute了什么值,当它顺利到达下一个action或者是.jsp时,它是带不出上一个request中的值的。
如果你要从一个action到一个action或者是从一个action到一个jsp并且要把值在request中带过去该怎么跳呢?
如下所示:
|
这边默认如果action方法返回SUCCESS就会触发这个跳转
/ indexInit
|
RequestDispatcher dispatcher = request.getRequestDispatcher("/jsp/login/login.jsp"); dispatcher.forward(request, response); |
我们打开这个login.jsp,它来自于原有的myssh工程,我们把头上的这些东西去掉,它们是struts1的标签:
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%> |
把