1、1实验四 Struts2 综合实验实验目的:1 正确使用组件结构,在业务控制器 action 中调用模型 model 完成业务逻辑;2 掌握 OGNL 的使用,在 JSP 和 action 中正确使用 EL;3 掌握在 Struts2 架构中,使用 action 的 rich 属性作为输入属性的方法。实验要求:1 设计正确的 web 组件结构,业务控制器 action 调用模型 model 完成业务逻辑;2 使用使用 action 的 rich 属性作为输入属性的方法。实验环境:MyEclips8.x+Struts2.0实验内容:正确使用 MVC 模式,严格区别三种角色,用 JSP 实现视图(
2、V),使用 action 实现控制器(C),使用 JavaBean 实现业务业务逻辑,完成一个简单的用户登录应用。实验步骤:准备工作同基本实验下面的实验分两种类型进行第一种类型,简单使用 struts2,实现登录检测功能,不考虑复杂的中文问题,并将业务逻辑直接放在用户定义的控制器 action 中。第二种类型,较综合使用 struts2,实现登录检测功能,用过滤器技术解决参数传递中的中文问题,用户定义的控制器 action 调用 bean 完成业务逻辑。Part 11. 启动 MyEclipse,创建一个 Web 工程,名称为 TestStruts2。2. 增加 Strut 功能查看配置文件。
3、(1)web.xml 文件配置:struts2org.apache.struts2.dispatcher.FilterDispatcherstruts2/*index.jsp(2)在 src 下新建三个文件:struts.xml,struts.properties , messageResource_zh_CN.properties。这三个文件的具体配置如下:/struts.xml/index.jsp/error.jsp/welcome.jsp 注释:这是 Struts2 的关键配置文件,现作如下讲解:(1) package 指出包名(可以指定任何名字) 和扩展的 xml 文件,这里用的是默认
4、的“struts-default“,包内可以包含多个 action。3(2) action 是关键的标识,指出 form 表单提交后用以处理的 action 类,注意这里的 “login“和 form 表单中的 action 是一致的。(3) action 里的 result 指出类处理完后的跳转的页面标识,例如,如果返回的是“error ”,则页面跳转到 error.jsp 页面。以后会添加更多复杂的配置信息。/struts.properties,配置本地化、国际化和字符编码信息struts.locale=zh_CNstruts.i18n.encoding=GB2312struts.cust
5、om.i18n.resources=messageResource/ messageResource_zh_CN.properties,配置具体的国际化对应信息,这里只列出了中文。/ messageResource_zh_CN.properties,配置具体的国际化对应信息,这里只列出了中文。loginPage=登录页面errorPage=错误页面succPage=成功页面failTip=对不起,您不能登录!用户名或密码错误!succTip=欢迎,$0,您已经登录!user=用户名sex=性 别age=年 龄birth=生 日pass=密 码login=登录reset=重置user.requi
6、red=用户名必须输入!pass.required=密码必须输入!注意:如果包含中文的文档不能保存,则需要修改相应文档的编码类型。导航 MyEclipse-Windows-Preferences-General-Content Type,将右边框中 text 前面的加号(+)展开,选择相应的文档类型,修改 Default encoding 的值为 GB2312,然后点击破右边的 Update按钮即可。3. 创建 Action。新建一个 LoginAction.java,包名为 com.action,继承了ActionSupport,用来处理登陆请求。/ LoginAction.java4pac
7、kage com.action;import com.opensymphony.xwork2.ActionSupport;import com.opensymphony.xwork2.ActionContext;public class LoginAction extends ActionSupportprivate static final long serialVersionUID = 1L;private String username;private String password;public String getUsername()return username;public vo
8、id setUsername(String username)this.username = username;public String getPassword()return password;public void setPassword(String password)this.password = password;public String execute() throws Exception/*判断用户名和密码,这里是固定的(scott,tiger),以后会根据数据库来验证*/if (getUsername().equals(“scott“)ActionContext.getCo
9、ntext().getSession().put(“user“, getUsername();return SUCCESS;else5return ERROR;4. 创建 JSP 。在/WebRoot/下创建三个 JSP:index.jsp,welcome.jsp ,error.jsp 。(1) 登录页面 index.jsp 用户测试的用户名和密码分别为:scott,tiger(2) 登录成功时跳转的页面 welcome.jsp 第一种获取用户名的方法:欢迎,第二种获取用户名的方法:用户名: 6(3) 登录错误时返回的页面 error.jsp 你输入的用户名: 5. 部署工程,启动服务器,打开
10、浏览器对登录功能进行测试。6. 总结Struts2 有很多的优势,其配置文件更加灵活和简洁,功能更加强大,特别是其简单易用、功能强大的标签库,具体的知识请查阅相关资料和老师课堂讲解。此时,(1) 如果在输入用户名时使用了中文(当然是在 action 中的名字改为中文的情况下),会出错,虽然重新访问页面输入中文是可以的。(2) 控制与业务逻辑没有分离。下面对这两个问题进行改进第二部分1 启动 MyEclipse,创建一个 Web 工程,名称为 MyStruts2。2 增加 struts 能力3 建立过滤器。因为从 Web 页面传到后台的中文经过 struts 过滤器后会变成乱码,为了解决这个问题
11、,需要重写这个过滤器,最简单的方法是写一个类继承 FilterDispatcher,在 src 目录下创建 com.filter 包,在包中建立 NewFilterDispatcher 类,继承 FilterDispatcher,代码如下:package com.filter;7import java.io.IOException;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.Servlet
12、Request;import javax.servlet.ServletResponse;import org.apache.struts2.dispatcher.FilterDispatcher;public class NewFilterDispatcher extends FilterDispatcher private static String encoding = “GB2312“;public void init(FilterConfig filterConfig) throws ServletException super.init(filterConfig);String e
13、ncodingParam = filterConfig.getInitParameter(“encoding“);if (encodingParam != null public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException request.setCharacterEncoding(encoding);super.doFilter(request, response, chain);4 在 web 部署描
14、述符中定义 struts2,相应的代码为:strutscom.filter.NewFilterDispatcherencoding8GB2312struts/*说明:(1) 该类是FilterDispatcher类的子类。(2) 该类有个成员变量,名为encoding,默认是“GB2312” 。(3) 注意在web.xml中,标签里多了标签,顾名思义,它的作用是初始化一个参数,里面定义了参数名和参数值。因此,在子类中,需要重写init方法,其中语句:String encodingParam = filterConfig.getInitParameter(“encoding“);的意义就是从we
15、b.xml中读出参数名为encoding的值,然后赋给子类中的encoding成员。(4)重写dofilter方法,加上:request.setCharacterEncoding(encoding);然后再调用父类的dofilter方法,这样就完成了编码的转换。(5)如果需要使用其它编码(如“UTF-8”等) ,只要改变中的值即可。5 建立业务对象建立包 com.bean,在其中建立 User.javapackage com.bean;public class Userprivate String name;private String password;public User() publi
16、c User(String name,String password) this.name=name;this.password=password;9public 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;6 创建 Action。新建一个 LoginAction.
17、java,包名为 com.action,继承了 ActionSupport,用来控制登录请求。/ LoginAction.javapackage com.action;import com.opensymphony.xwork2.ActionSupport;import com.opensymphony.xwork2.ActionContext;import com.bean.User;public class LoginAction extends ActionSupportprivate static final long serialVersionUID = 1L;private Use
18、r usr;public User getUsr() return usr;public void setUsr(User usr) if(usr = null) usr = new User();this.usr = usr;public String execute() throws Exception/*判断用户名和密码,这里是固定的(斯柯达,tiger), 以后会根据数据库来验证*/if (usr.getName().equals(“斯柯达“ )10elsereturn ERROR;说明:(1) LoginAction 类中定义了登录页面中出现的 VO 对象 usr 之相关属性的get
19、、set 方法。按 OGNL 和 Struts2 的框架要求,在表单提交时,通过表达式语言(EL ) usr.name 和 usr.password 访问对象数据成员的 Action,在经过 struts 过滤器时,其容器会自动调用 getUsr()方法和“usr”这个成员变量。由于 usr 是 User 类的一个对象,它本身还有 name 等属性,因此struts 还会自动调用该对象的“setName”方法,为 name 属性赋值,Struts2 通过这种方式完成参数的传递,在 User 类的定义中相应成员变量必须有 get、set 方法。其中“usr.name”是表达式语言(Express
20、ion Language,简称为 EL)中的语句。表达式语言由 XWork 框架提供支持,XWork 表达式语言的核心是 OGNL(Object Graph Notation Language), OGNL 是一种功能强大,技术成熟,应用广泛的表达式语言。用户在表单中输入的数据,会被保存到一个叫做“值堆栈”(OgnlValueStack)的对象中,通过表达式语言的语句来获取或设置值堆栈中的数据。那些通过 set方法设置的值,在页面中可以通过如这样的方法重新获得。(2) LoginAction 类的 execute()继承了父类的方法,其中的 SUCCESS 和 ERROR 是父类中定义的常量,
21、其值分别为 success 和 error,它们分别与struts.xml 文件中两个 标签的相应 name 属性值对应。7 定义其它配置文件在 src 下新建三个文件:struts.xml,struts.properties , messageResource_zh_CN.properties,其方法和第一部分中11的相应部分相同。7. 创建 JSP 在/WebRoot/下创建三个 JSP:index.jsp,welcome.jsp,error.jsp。(1) index.jsp 登录页面用户测试的用户名和密码分别为:斯柯达,tiger说明: 标签调用的值都会在messageResource
22、_zh_CN.properties文件进行初始化,例如其值对应设置为: user=用户名,因而在页面中直接使用标签关键字“user“就可以显示其对应的值“用户名”。 因为要传中文信息,所以页面中使用的字符集改成了GB2312。虽然使用了中文过滤器,还要设置页面的字符集为GB2312,因为中文过滤器只负责传递途中的过滤处理。(2)输入正确时的返回页面文件为 welcome.jsp欢迎您,12(3) 输入错误时的返回页面文件 error.jsp 你输入的 8. 部署工程,启动服务器,打开浏览器对登录功能进行测试。在IE 中输入:Http:localhost:8080/MyStruts/,出现登录页
23、面为下图所示:如果输入正确,用户名称:斯柯达,密码:tiger,返回的页面为:13上述结果表明,请求页面经过过滤器,正确地处理了中文。如果输入错误信息,则返回结果为:9. 总结相比 Struts1,Struts2 有很多的优势,其配置文件更加灵活和简洁,功能更加强大,14特别是其简单易用、功能强大的标签库和过滤器,具体的知识请查阅相关资料和老师课堂讲解。体会Struts2 强大的类型转换功能:用户信息可以更加丰富,如:package com.bean;import java.util.*;public class Userprivate String name;private String p
24、assword;private String sex;private int age;private Date birth;public User() public User(String name,String password,String sex,int age,Date date) this.name=name;this.password=password;this.sex=sex;this.age=age;this.birth=date;public String getName() return name;public void setName(String name) this.
25、name = name;public String getPassword() return password;public void setPassword(String password) this.password = password;public String getSex() return sex;15public void setSex(String sex) this.sex = sex;public int getAge() return age;public void setAge(int age) this.age = age;public Date getBirth()
26、 return birth;public void setBirth(Date date) this.birth = date;相应的登录页面如下面的login.jsp用户测试的用户名和密码分别为:斯柯达,tiger为了方便用户的输入,在 login.jsp 中使用了列表。将 welcome.jsp 相应地改为下面的next.jsp,注意修改 struts.xml 中的信息16“ My JSP next.jsp starting page以下是你输入的信息:重新部署,在IE中输入:http:/localhost:8080/MyStruts2/Login.jsp,在请求的页面中输入正确的信息返回
27、页面下图所示:17上面操作一切正常,没有显示的类型转换。因为 Struts 2 内建的 OGNL 表达式的支持,可以用非常简单方式将请求参数转换成复合类型。如果系统的 Action 类代码片段如下:public class LoginAction extends ActionSupportprivate static final long serialVersionUID = 1L;private User usr;public User getUsr() return usr;public void setUsr(User usr) if(usr = null) usr = new User
28、();this.usr = usr;public String execute() throws Exception/*判断用户名和密码,这里是固定的(斯柯达,tiger), 以后会根据数据库来验证*/if (usr.getName().equals(“斯柯达“ )18elsereturn ERROR;上面的 Action 类中同样包括了一个复合类型属性,但我们可以无须类型转换器,而是利用OGNL 表达式来直接生成 usr 实例。这种方式主要是在指定输入信息的 JSP 页面中,并不是直接给出 usr 属性对应表单域,而是将表单域的 name 属性对应到 usr 属性的属性。看如下代码段:上面表
29、单包含了六个请求参数:usr.name、usr.age、usr.sex、usr.birth 、usr.password,这是一种表达式的写法,系统会把usr.name等参数的值赋值给Action实例的usr属性的name属性,也将usr的其它属性做类似处理。通过这种方式,一样可以将输入的字符串参数转换成复合类型对象,但在使用这种方式时有如下几点需要注意:因为 Struts 2 是需要直接创建一个复合类(User 类)的实例,因此系统必须为该复 合类提供无参数的构造函数。如果希望使用 usrname 请求参数的形式为 Action 实例的 usr 属性的 name 属性赋 值,则必须为 usr 属性对应的复合类(User 类)提供 setName 方法,因为 Struts 2 是通过调用该方法来为该属性赋值的。当然 Action 类中还应该包含 setUser 方法。更极端的情况,我们甚至可以直接生成 Collection,或者 Map 实例。