第十部分_Struts2.1详述与MVC设计模式

第十部分_Struts2.1详述与MVC设计模式

讲了诸多原理性的东西,下面该来看看如何实践了:

首先,在MyEclipse中新建一个Web Project,命名为struts2(注意这里我用的版本是struts2.1.6),规范级别选择Java EE 5.0,当然了,我们仍然需要告诉Tomcat我们的项目在哪里,因此到Tomcat安装目录下的conf文件夹下的server.xml文件,为了节约时间,我们把test项目的上下文放到注释中,以免每次启动tomcat,都要加载该项目,相关配置部分如下:

 <!--

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"  

               prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>

<Context path="/test" docBase="D:\JavaWeb\test\WebRoot" reloadable="true"/>



        -->



<Context path="/struts2" docBase="D:\JavaWeb\struts2\WebRoot" reloadable="true"/>





      </Host>

    </Engine>

  </Service>

</Server>

重启tomcat服务器,访问http://localhost:8080/struts2,页面出现"This is my JSP page." 表示我们的项目已经纳入Tomcat的管理之下了。我们将structs2框架集成到我们新建的项目中,其实就是将structs2提供的JAR包添加到项目了,其中我们需要的JAR包有(在解压好的structs的解压文件中的lib目录下)commons-fileupload-1.2.1.jar、commons-logging-1.0.4.jar、freemarker-2.3.13.jar、ognl-2.6.11.jar、struts2-core-2.1.6.jar、xwork-core-2.1.2.jar共六个文件选中复制,回到MyEclipse,粘贴到WebRoot下面的WEB-INF下的lib目录下,这样这些第三方库就可以为我们所用了。

下面,我们用struts2写一个经典的hello world,标志学习struct2的起步:

在WebRoot下新建一个helloworld.jsp文件,将body中的内容更改为Hello World。当然我们可以直接访问http://localhost:8080/struts2/helloworld.jsp。但是这里我们通过struct2的控制实现间接访问:在src目录下新建一个包com.test.action,然后再改包下建立一个名为helloworld的类,定义一个execute方法:

package com.test.action;



public class helloworld

{

	public String execute() throws Exception

	{

		return "success";

	}

}

struts2的一个核心的东西是一个配置文件,该文件的默认名字为struts.xml,这个文件就描述了整个流程的转发以及执行过程。在src下新建一个名为struts的xml文件,解压缩struts2目录下的apps下的struts2-blank文件,展开下面的WEB-INF,打开src,打开java,找到struts.xml文件,打开将其头部的dtd(验证我们的struts.xml文件)信息粘贴到我们的新建的xml文件中(这里访问的时候并不是去网络中找dtd文件,这样的话dtd文件较大的话会拖慢运行速度,实际上它是先到本机中寻找,找不到再到网络中找,我们这里就是在本机的struts2-core-2.1.6.jar下面的struts-2.0.dtd中):

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

利用MyEclipse的提示功能完整的xml文件内容如下(其中extends="struts-default"是为了引入本机struts2-core-2.1.6.jar下面的struts-default.xml,这样我们就拥有了struts2的基本功能):

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="struts2" extends="struts-default"> <action name="helloworld" class="com.test.action.HelloWorld"> <result name="success">/helloworld.jsp</result> </action> </package> </struts>

  MyEclipse会自动的把这个文件copy一份复制到项目的WEB-INF目录下的classes目录下,我们之所以建立在src目录下,是为了在IDE中可以编辑它。

接下来,在web.xml中配置如下(配置之前需要的相关信息可以在D:\Program Files\struts-2.1.6\docs\struts2-core\apidocs里找到index.html中找到org.apache.struts2包下面的FilterDispatcher类,里面有一个信息:Deprecated. Since Struts 2.1.3, useStrutsPrepareAndExecuteFilter instead orStrutsPrepareFilter and StrutsExecuteFilter if needing using the ActionContextCleanUp filter in addition to this one,用来提示我们用新的类代替旧的类,可以看到StrutsPrepareAndExecuteFIlter的包名为:org.apache.struts2.dispatcher.ng.filter

):

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" 

	xmlns="http://java.sun.com/xml/ns/javaee" 

	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 

	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  

  <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>

注意:过滤器也是在web应用启动的时候被加载的,相当于servlet配置了一个load-on-startup属性一样。

访问http://localhost:8080/struts2/helloworld.action,输出hello world即为成功。

最后,最重要的事情是,程序的运转流程

首先我们在地址栏键入http://localhost:8080/struts2/helloworld.action,请求访问helloworld.action这个资源,请求到达了Tomcat服务器端,于是Tomcat到web.xml中找到了filter-mapping,因为其url-pattern被我们设定为/*,于是所有的客户想要访问的所有资源都需要经它过滤,经filter-name找到相应的filter(web应用启动时便被加载了),这里就是我们的struts2,根据这个filter-name找到响应的filter-class:org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter,流程转到struts.xml中,首先找到相应的包:struts2,然后找相应的action:name属性为helloworld,与该名字所对应的是class:com.test.action.HelloWorld进行处理,流程转到HelloWorld类,执行其execute方法,返回值为success,之后流程又返回到struts.xml中的action,找到result中name属性为success的,于是流程转到helloworld.jsp,于是我们的hello world输出来了。

此外一个,可能的疑惑是,一个客户请求对应一个request和response,作为doGet和doPost的两个参数,为什么我们整个过程中都没有看到过request和response对象呢,然而程序仍然能正常运转,但是,这只是表面上来看是这样的,底层它既然是基于HTTP协议的一个框架,肯定是有request和response,只不过struts2巧妙的把它们隐藏起来了,因此我们看不到他们。

上面的程序是处理一个静态的页面,下面我们来一个复杂点的,涉及到动态的页面。下面我们就用struts2来实现一个简单的登录系统:

首先新建一个login.jsp:

<body>

  <form action="login.action">

    username: <input type="text" name="username" size="20"/><br>

    password: <input type="password" name="password" size="20"/><br/>

    

    <input type="submit" value="submit"> 

   </form>

  </body>

然后,新建一个类,名为LoginAction(其中的username 和 password作为成员变量必须与表单中的一致,并且为其生成set和get注入方法):

package com.test.action;



public class LoginAction

{

	private String username;

	

	private String password;



	public String getUsername()

	{

		return username;

	}



	public void setUsername(String username)

	{

		this.username = username;

	}



	public String getPassword()

	{

		return password;

	}



	public void setPassword(String password)

	{

		this.password = password;

	}

	

	public String execute() throws Exception

	{

		return "success";

	}

}

接下来,配置struts.xml,在原来的基础上增加一个名为login的action:

<struts>

		

		<package name="struts2" extends="struts-default">

		

			<action name="helloworld" class="com.test.action.HelloWorld">

				<result name="success">/helloworld.jsp</result>

			</action>

			

			<action name="login" class="com.test.action.LoginAction">

				<result name="success">/result.jsp</result>

			</action>

		</package>

	

</struts>

最后,完成我们还缺少的一环,处理客户信息,新建一个result.jsp:

 <body>

    username: ${requestScope.username }<br/>

    password: ${requestScope.password }

  </body>

重启Tomcat,访问:http://localhost:8080/struts2/login.jsp,输入zhangsan,12345,跳转到http://localhost:8080/struts2/login.action?username=zhangsan&password=12345,并且显示username和password信息,即为成功。这种Get提交方式不太安全,因此可以把表单的提交该为post方式。

学习内容:

  • Struts2入门及基本配置
  • Struts2核心概念及原理
  • Struts2类型转换
  • Struts2输入校验
  • Struts2实现文件上传及下载
  • Struts2深入探索(源代码)
  • Struts2的拦截器(Intercepter)
  • Struts2的国际化(Internationalization)
  • Struts2标签库

Struts2是什么?

  Struts2 = Struts + WebWork

为何Struts2使用XWork?

  XWork是一个通用命令模式的框架,WebWork = WebWork Core + XWork,Struts2 = Struts 2 Core + XWork。Struts2把Web功能转换提供给XWork。

第十部分_Struts2.1详述与MVC设计模式

XWork提供了什么?

  实现独立运行的命令模式框架:Action作为命令对象存在于XWork中

  增加了高级功能

    拦截器:包括设置表单参数,处理文件上传等

    结果(Result):包括多个Action之间的链接,转向表示层

    简单的IoC(或称DI,依赖注入)容器,可给Action对象注入值(Spring)

    强大的对象查询语言-OGNL

    自动类型转换

    元数据驱动的验证框架

    插件机制

Struts Core提供了什么?

  • 封装HTTP请求/响应对象为Map
  • 处理Session/Application范围
  • ServletDispatcher转换HTTP请求执行Action
  • 提供了Web层的拦截器
  • 将Result转换为具体的redirect&dispatch,或者其它表示层

系统架构:

  • 接收到请求
  • FilterDispatcher找到合适的Action
  • 拦截器调用
  • Action中的方法执行("核心"业务)
  • Result进行输出

Action:

  Action是命令对象;Action应尽量简单;Action和任何Web对象无关;Action接口只有一个方法:

public interface Action

{

    public String execute() throws Exception;

}

需要注意的一点:Struts2下载包内不包含XWork源码,如有需要需从XWork网站下载。

Struts2基本开发配置(完成Struts2 Hello Workd):

  • 启动MyEclipse
  • 创建Web Project
  • 添加必需的Struts2 jar文件
  • 向web.xml加入struts2过滤器
  • 创建Action类HelloWorldAction
  • 创建JSP表示层页面HelloWorld.jsp
  • 创建struts.xml并加入action定义
  • 运行测试

  执行流程为:action->FilterDispatcher->HelloWorldAction.execute()->"success"->struts.xml找到Result->显示HelloWorld.jsp

  看不到的过程-拦截器:设置表单参数;设置请求属性

开发简单登录应用:

  • 编写表单页面login.jsp
  • 编写登录结果页面login_result.jsp
  • 编写Action类UserAction
  • 给struts.xml加入Action定义
  • 运行测试
  • 执行流程
  • 改进:登录失败返回输入页面

Struts2和1的异同点

  不同点:FormBean被Action属性取代;ActionForWard被Result取代;Action类中不直接出现Servlet对象;引入了package的概念;引入了拦截器的概念;Struts2的开发大大简化

  相同点:都是MVC架构;均提供了控制器和流程跳转功能;监听特定的URL地址来实现功能.action;均提供了切换view层的功能;提供了类似的标签库:表单和逻辑;都支持国际化功能

补充:package与action的关系,就好像Java中的包和类的关系一样,一个package可以包含多个action,Java中的包是有名字的,struts也是如此,这个名字是可以随意起的,此外,struts中的包还允许继承,如我们的struts.xml中,extends="struts-default",在MyEclipse中打开Struts2-core-2.1.6.jar,可以看到里面有一个struts-default.xml的文件, 可以看到他的包<package name="struts-default" abstract="true">,因此我们的struts.xml继承了这个名字为struts-default的包,具有了该包定义的所有功能,abstract为true表示该包为抽象包,不能直接用,我们自己写的struts就是一个具体的包。

下面我们用struts标签库来写一个login2.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>

<%@ taglib uri="/struts-tags" prefix="s" %>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <base href="<%=basePath%>">

    

    <title>My JSP 'login2.jsp' starting page</title>

    

	<meta http-equiv="pragma" content="no-cache">

	<meta http-equiv="cache-control" content="no-cache">

	<meta http-equiv="expires" content="0">    

	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

	<meta http-equiv="description" content="This is my page">

	<!--

	<link rel="stylesheet" type="text/css" href="styles.css">

	-->



  </head>

  

  <body>

   	<s:form action="login.action">

   		<s:textfield name="username" label="username"></s:textfield><br/>

   		<s:password name="password" label="password"></s:password>

   		<s:submit value="submit"></s:submit>

   	</s:form>

  </body>

</html>

注意<%@ taglib uri="/struts-tags" prefix="s" %>和body中的内容是我们自己添加的。此外我们可以按住Ctrl键,鼠标点击,跟进其源代码,在<s:textfield...这一行,跟进去发现一个8000多行的tld(struts-tags.tld)文件,其<uri>/struts-tags</uri>,此即我们的taglib的uri的来源。

此外,还用注意的一点,标准的HTML表单默认提交方法是Get,而Struts2的表单默认的提交方式是Post。还有,表单中的.action可以省略,它是struts2默认的后缀名。

你可能感兴趣的:(struts2)