1.4 Struts 2简单应用
接下来将完成一个最简单的应用。用户进入一个登录页面,输入用户名、密码,如果用户输入的用户名和密码符合要求,则进入一个欢迎页面;如果用户输入错误,则进入一个错误提示页面。为了专注于Struts 2的核心流程,案例中业务逻辑处理采用简化的方式来实现,而非到数据库中查询结果。
1.4.1 下载和安装Struts 2
本书所使用的Struts 2的版本是Struts 2.3.14,大家可以下载这个版本使用。进入http://struts.apache.org/download.cgi#struts2314站点,下载struts-2.3.14-all.zip这个压缩文件,这个文件中包含了Struts 2产品的所有内容。将下载文件解压缩,能看到下面介绍的各个目录。
apps:该目录中包含了基于Struts 2的示例应用,这些示例应用对于学习者是非常有用的。
docs:该目录中包含了Struts 2的相关文档,包括Struts 2的快速入门、Struts 2文档以及API文档等内容。
lib:该目录中包含了Struts 2框架的核心类库,以及Struts 2的第三方插件类库。
src:该目录中包含了Struts 2框架的全部源代码。
1.4.2 为Web应用添加Struts 2支持
● 创建Web工程并复制jar包
在Eclipse中创建一个名为Struts2_hello的动态Web工程。从之前下载并解压缩的lib目录下,复制以下几个Jar包(见图1.4)到工程的WEB-INF/lib目录下。
图1.4 导入Struts 2所需Jar包
● 修改web.xml,配置前端控制器
<?xml version="1.0" encoding="UTF-8"?> <web-app …> <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> </web-app>
该配置的含义是使用Struts 2前端控制器StrutsPrepareAndExecuteFilter(过滤器)拦截所有的请求。
1.4.3 开发Web应用程序
● 创建请求页面
新建login.jsp,内容如下:
<body> <form action="login" method="post"> Email:<input type="text" name="email" /><br> 密码:<input type="password" name="password" /><br> <input type="submit" value="确认"/> </form> </body>
这是一个非常简单的JSP,仅有一个表单,表单中需要用户输入用户名和密码。
● 开发Action
新建org.bd.struts2.hello.LoginAction,内容如下:
public class LoginAction { public String execute(){ if(email.equals("z@163.com")&&password.equals("123456")) return "success"; else return "error"; } private String email; private String password; //省略getter&setter方法 }
对于这段代码,有必要进行一些说明:
(1)这个LoginAction类就是Struts 2的Action部分,处理业务流程的工作单元,它可以不继承任何的类。
(2)LoginAction类有两个属性(域成员),分别是email和password,它们和表单对应标签的name属性必须一致,同时LoginAction类中必须有这两个域成员的setter方法。
(3)public String execute()方法的定义是固定的,它不依赖于任何Servlet API或Struts2 API,这是真正处理业务的地方,它将被框架以某种方式自动调用。另外,在该方法中可以直接使用email和password两个域成员而不必担心出现空指针异常,这是因为Struts 2框架在方法调用前,自动将表单内和域成员同名的请求参数值赋值给域成员,所以开发人员可以假设,执行此方法时所有域成员已经被初始化了。
(4)execute()方法里的内容仅仅是模拟业务逻辑的实现,在真正的开发中,它应该调用Service层(有时也命名为business层或bi2层)的业务方法。execute()方法返回的字符串可以理解为Result组件的名称,在随后内容中会讲解它的作用。
● 配置Action
(1)解压struts-2.3.14\apps目录下的struts2-blank.war文件,复制\struts2-blank\WEB-INF\classes目录下的struts.xml文件到Struts2_hello\src目录下。
(2)struts.xml是Struts 2的映射文件,用于映射具体请求的URL到对应处理的Action类,所以需要将这两项内容添加到这个文件中。修改复制进来的struts.xml文件,只保留以下的内容:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="default" namespace="/" extends="struts-default"> </package> </struts>
(3)在package节点中添加以下内容,配置URL与Action的映射以及Action返回字符串与视图(可以是JSP页面)的映射。
<!--URL与Action的映射 --> <action name="login" class="org.bd.struts2.hello.LoginAction"> <!-- 返回字符串与视图的映射 --> <result name="success">/index.jsp</result> <result name="error">/error.jsp</result> </action>
既然是URL与Action的映射,那么读者应该注意到此处action节点的name属性应该与请求表单的action属性一致,而result节点的name属性应该与LoginAction类execute()方法返回的字符串一致。
● 增加视图
经过上面的步骤,这个简单的Struts 2应用几乎可以运行了,最后还需要为该应用增加两个JSP文件,用于提供给用户的视图显示。这两个JSP文件分别是error.jsp页面和index.jsp页面,它们只是包含了简单的提示信息。
index.jsp的代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <body> 您已经登录! </body> </html>
error.jsp的代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <body> 登录失败! </body> </html>
部署Web应用之后,访问login.jsp页面,用户名和密码分别输入“z@163.com”和“123456”,提交后可以看到“您已经登录!”,否则显示“登录失败!”。
1.4.4 案例小结
在学习本节案例的过程中,读者应该常常对比图1.3,时刻提醒自己正在完成的是MVC的哪个关注点。修改web.xml是配置Filter让前端控制器发挥作用,编写Action是业务逻辑控制器的体现,两个结果JSP则是输出的结果视图。而struts.xml这个重要的配置文件则作为纽带,将表单请求与Action映射起来,并将Action返回字符串与视图映射起来。
为帮助大家记忆,在使用Struts 2框架时,开发者需要保持三个一致。
(1)表单的action属性应该和struts.xml中配置的action的name属性一致。
(2)表单内用于输入参数的标签name属性,应该与Action的域成员名字保持一致。
(3)Action的execute()方法返回的字符串应该与struts.xml中配置的result节点的name属性一致。