首页 > 代码库 > Struts2

Struts2

一,什么是框架?  所谓框架就是提供了一组统一的接口和编程方式的可以重用组件,同时我们可以在框架中扩充我们自己的特定逻辑。

二,MVC设计模式 

将应用程序分为3个部分:模型 Model,视图View,控制器Controller; 

模型组件:负责业务逻辑;   模型包含应用程序的核心功能。模型封装了应用程序的状态。有时它包含的唯一功能就是状态。它对视图或控制器一无所知。 

视图组件:负责表示业务范围的视图;   视图提供模型的表示。它是应用程序的 外观。视图可以访问模型的读方法,但不能访问写方法。此外,它对控制器一无所知。当更改模型时,视图应得到通知。 

控制器组件:负责控制用户输入的流和状态;   控制器对用户的输入作出反应。它创建并设置模型。   

Struts,它是使用 servlet 和 JavaServer Pages 技术的一种MVC 实现;  Struts,Apache组织的一个项目,MVC 的一种开放源码实现;

三,什么是Struts框架  Struts 是一组相互协作的类、servlet 和 JSP 标记组成的一个可重用的 MVC 2 设计。  这个定义表示 Struts 是一个框架,而不是一个库,但 Struts 也包含了丰富的标记库和独立于该框架工作的实用程序类。

四,Struts 概览
1,Client browser(客户浏览器)    来自客户浏览器的每个 HTTP 请求创建一个事件。Web 容器将用一个 HTTP 响应作出响应。
2,Controller(控制器)    控制器接收来自浏览器的请求,并决定将这个请求发往何处。   

就 Struts 而言,控制器是以 servlet 实现的一个命令设计模式。 struts-config.xml 文件配置控制器命令。
3,业务逻辑    业务逻辑更新模型的状态,并帮助控制应用程序的流程。   

就 Struts 而言,这是通过作为实际业务逻辑“瘦”包装的 Action 类完成的。
4,Model(模型)的状态    模型表示应用程序的状态。业务对象更新应用程序的状态。   

 ActionForm bean 在会话级或请求级表示模型的状态,而不是在持久级。    JSP 文件使用 JSP 标记读取来自 ActionForm bean 的信息。
5,View(视图)    视图就是一个 JSP 文件。其中没有流程逻辑,没有业务逻辑,也没有模型信息 —— 只有标记。   

标记是使 Struts 有别于其他框架(如 Velocity)的因素之一。

五, Struts中的Controller(控制器)  命令设计模式的实现:   Struts 的控制器将事件(事件通常是 HTTP post)映射到类的一个 servlet.
ActionServlet (Command) 创建并使用 Action 、 ActionForm 和 ActionForward .   通过struts-config.xml 文件配置该 Command.从而扩展 Action 和 ActionForm 来解决特定的问题。   可以通过扩展 ActionServlet 来添加 Command 功能。    

 在Struts框架中控制器组件由三个部分构成:  

1,消息控制模块;    用户所有的提交请求都发往消息控制模块,在由消息总线模块根据视图映射模块找到消息处理模块来执行处理逻辑。   

 消息控制模块接收所有用户的请求,并根据请求视图找到处理。    Strtus中通过ActionServlet和RequestProcessor类来完成。  

2,消息处理模块;    该模块执行该消息的逻辑处理,因此通常由用户扩展实现。    Struts中通过Action类来实现。  

3,视图映射模块;    控制器逻辑和视图逻辑之间的结合是通过配置模块和配置文件建立其的链接。    Struts中配置模块通过ModuleConfig类来完成,而配置文件由struts-config.xml文件提供。 

六,Struts中的View(视图)  视图组件通过JSP组件实现的。Struts框架对视图组件进行了扩展和封装。  

Struts对视图的扩展提供了一组扩展服务器标签用来提供视图显示以及传递数据到处理缓冲,而处理缓冲由ActionForm的扩展类来实现。 

Struts框架利用ActionForm Bean来实现视图与控制器之间的数据的交互,维持会话级或请求级的模型的状态。   

服务器标签主要包括:   Html视图标签;   Logic逻辑流程控制标签;   Bean数据缓冲读取标签;   

 

七,Struts中的Model(模型) 

1,Struts框架中并没有定义特定的模型组件,而是希望由用户自己决定选择合理的模型组件。  

 J2EE中可用的模型组件包括:    JavaBean 用户定义组件;    EJB 组件,由EJB容器实现组件;    JDO 未来J2EE数据访问模型;    一些扩展框架如:Hibernate; 

2,模型中状态的级别   会话级或请求级:ActionForm bean来维持 ;   持久级:模型组件来维持;

 

代码:

index.jsp:

代码

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%
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="http://www.mamicode.com/">

<title>测试ActionForm</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="http://www.mamicode.com/styles.css">
-->
</head>

<body>
<h1>测试ActionForm</h1>
<hr>
<li>测试动态ActionForm</li><br>
<form action="dyanactionform.do" method="post">
姓名:<input type="text" name="username"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="http://www.mamicode.com/提交"> 
</form> 
<p>
<li>测试struts上传文件</li><br>
<form action="upload.do" method="post" enctype="multipart/form-data">
标题:<input type="text" name="title"><br>
文件:<input type="file" name="myfile"><br>
<input type="submit" value="http://www.mamicode.com/提交">
</form>
<p>
<li>空字段测试</li><br>
<form action="blankfield.do" method="post">
姓名:<input type="text" name="username"><br>
<input type="submit" value="http://www.mamicode.com/提交">
</form>
<p>
<li>测试ActionForm类型转换器</li><br>
<form action="typeconvert.do" method="post">
intValue:<input type="text" name="intValue"><br>
doubleValue:<input type="text" name="doubleValue"><br>
booleanValue:<input type="text" name="booleanValue"><br>
java.sql.Date:<input type="text" name="sqlDate"><br>
java.util.Date:<input type="text" name="utilDate"><br>
<input type="submit" value="http://www.mamicode.com/提交">
</form>
</body>
</html>

配置文件

struts-config.xml

代码

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">

<struts-config>
<form-beans>
<form-bean name="dynaForm" type="org.apache.struts.action.DynaActionForm">
<form-property name="username" type="java.lang.String"/>
<form-property name="age" type="java.lang.Integer"/>
</form-bean>

<form-bean name="uploadForm" type="com.bjsxt.struts.UploadActionForm"/>

<form-bean name="blankFieldForm" type="com.bjsxt.struts.BlankFieldActionForm"/>

<form-bean name="typeconvertForm" type="com.bjsxt.struts.TypeConvertActionForm"/>
</form-beans>

<action-mappings>
<action path="/dyanactionform"
type="com.bjsxt.struts.DynaActionFormTestAction"
name="dynaForm"
scope="request"
>
<forward name="success" path="/dyna_actionform.jsp"/>
</action>

<action path="/upload"
type="com.bjsxt.struts.UploadTestAction"
name="uploadForm"
scope="request"
>
<forward name="success" path="/upload_success.jsp"/>
</action>

<action path="/blankfield"
type="com.bjsxt.struts.BlankFieldTestAction"
name="blankFieldForm"
scope="request" 
>
<forward name="success" path="/blankfield_success.jsp"/>
</action>

<action path="/typeconvert"
type="com.bjsxt.struts.TypeConvertTestAction"
name="typeconvertForm"
scope="request"
>
<forward name="success" path="/typeconvert_success.jsp"/> 
</action>
</action-mappings>

<controller maxFileSize="10M"/>

<plug-in className="com.bjsxt.struts.UtilDateConverterInitWithPlugin"/>
</struts-config>

1、AtionForm

 

代码

package com.bjsxt.struts;

import org.apache.struts.action.ActionForm;

/**
* 测试空字段
* @author Administrator
*
*/
public class BlankFieldActionForm extends ActionForm {

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

2:

代码

package com.bjsxt.struts;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

/**
* 测试空字段
* @author Administrator
*
*/
public class BlankFieldTestAction extends Action {

@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
return mapping.findForward("success");
}

}

3.

代码

<%@ page language="java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030"%>
<%@ page import="com.bjsxt.struts.*" %> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>Insert title here</title>
</head>
<body>
<%
BlankFieldActionForm form = (BlankFieldActionForm)request.getAttribute("blankFieldForm");
%>
<li>jsp脚本</li><br>
姓名:<%=form.getUsername() %><br>
密码:<%=form.getPassword() %><br>
<p>
<li>el表达式</li><br>
姓名:${blankFieldForm.username }<br>
密码:${blankFieldForm.password }<br>
</body>
</html>

业务逻辑类

DynaActionFormTestAction.java

1:

代码

package com.bjsxt.struts;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;

/**
* 测试动态ActionForm
* @author Administrator
*
*/
public class DynaActionFormTestAction extends Action {

@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
DynaActionForm daf = (DynaActionForm)form;
String username = (String)daf.get("username");
Integer age = (Integer)daf.get("age");
System.out.println("username=" + username);
System.out.println("age=" + age);
return mapping.findForward("success");
}

}

2:成功的返回页面

dyna_actionForm.jsp

代码

 

<%@ page language="java" contentType="text/html; charset=GB18030"

    pageEncoding="GB18030"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=GB18030">

<title>Insert title here</title>

</head>

<body>

    用户名称:${dynaForm.map.username }<br>

    年龄:${dynaForm.map.age }<br>

</body>

</html>

 

2、struts上传文件

代码

 

package com.bjsxt.struts;

 

import org.apache.struts.action.ActionForm;

import org.apache.struts.upload.FormFile;

 

/**

 * 上传ActionForm

 * @author Administrator

 *

 */

public class UploadActionForm extends ActionForm {

 

    private String title;

    

    //必须采用FormFile

    private FormFile myfile;

 

    public String getTitle() {

        return title;

    }

 

    public void setTitle(String title) {

        this.title = title;

    }

 

    public FormFile getMyfile() {

        return myfile;

    }

 

    public void setMyfile(FormFile myfile) {

        this.myfile = myfile;

    }

}

 

2.代码

 

package com.bjsxt.struts;

 

import java.io.FileOutputStream;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.apache.struts.action.Action;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.upload.FormFile;

 

/**

 * 上传Action

 * @author Administrator

 *

 */

public class UploadTestAction extends Action {

 

    @Override

    public ActionForward execute(ActionMapping mapping, ActionForm form,

            HttpServletRequest request, HttpServletResponse response)

            throws Exception {

        UploadActionForm uaf = (UploadActionForm)form;

        System.out.println("title" + uaf.getTitle());

        FormFile myFile = uaf.getMyfile();

        if (myFile != null) {

            System.out.println("fileName=" + myFile.getFileName());

            

            FileOutputStream fos = new FileOutputStream("c:\\" + myFile.getFileName());

            fos.write(myFile.getFileData());

            fos.flush();

            fos.close();

        }

        return mapping.findForward("success");

    }

 

}

 

成功返回页面

upload_success.jsp

代码

 

<%@ page language="java" contentType="text/html; charset=GB18030"

    pageEncoding="GB18030"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=GB18030">

<title>Insert title here</title>

</head>

<body>

    标题:${uploadForm.title}<br>

    文件名:${uploadForm.myfile.fileName  }<br>

</body>

 

</html>

类型转换

代码

 

package com.bjsxt.struts;

 

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Date;

 

import org.apache.commons.beanutils.Converter;

 

/**

 * java.util.Date类型转换器

 * @author Administrator

 *

 */

public class UtilDateConverter implements Converter {

 

    public Object convert(Class type, Object value) {

        System.out.println("UtilDateConverter.value="http://www.mamicode.com/+ value);

        if (value =http://www.mamicode.com/= null) {

            return value;

        }

        if (value instanceof Date) {

            return value;

        }

        Date d = null;

        if (value instanceof String) {

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

            try {

                d = sdf.parse((String)value);

            } catch (ParseException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }

        return d;

    }

 

 

}

 

2.代码

 

package com.bjsxt.struts;

 

import java.util.Date;

 

import javax.servlet.ServletException;

 

import org.apache.commons.beanutils.ConvertUtils;

import org.apache.struts.action.ActionServlet;

import org.apache.struts.action.PlugIn;

import org.apache.struts.config.ModuleConfig;

 

public class UtilDateConverterInitWithPlugin implements PlugIn {

 

    public void destroy() {

    }

 

    public void init(ActionServlet servlet, ModuleConfig config)

            throws ServletException {

        System.out.println("UtilDateConverterInitWithPlugin.init()");

        ConvertUtils.register(new UtilDateConverter(), Date.class);

    }

}

3.代码

 

package com.bjsxt.struts;

 

import java.util.Date;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

 

import org.apache.commons.beanutils.ConvertUtils;

 

/**

 * 注册java.util.date转换器

 * @author Administrator

 *

 */

public class UtilDateConverterInitWithServlet extends HttpServlet {

 

    @Override

    public void init() throws ServletException {

        System.out.println("UtilDateConverterInitWithServlet.init()");

        ConvertUtils.register(new UtilDateConverter(), Date.class);

    }

 

}

 

成功返回页面

typeconvert_success.jsp:

代码

 

<%@ page language="java" contentType="text/html; charset=GB18030"

    pageEncoding="GB18030"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=GB18030">

<title>Insert title here</title>

</head>

<body>

    intValue:${typeconvertForm.intValue }<br>

    doubleValue:${typeconvertForm.doubleValue }<br>

    booleanValue:${typeconvertForm.booleanValue }<br>

    java.sql.dateValue:${typeconvertForm.sqlDate }<br>

    java.util.utilValue:${typeconvertForm.utilDate }<br>

</body>

</html>

 

 

 讲解

1、动态ActionForm
 动态ActionForm是为了避免标准ActionForm膨胀而设计的,使用动态ActionForm可以获得标准
 ActionForm的所有功能
 * 在struts-config.xml文件中定义动态ActionForm,如:
 <form-beans>
  <form-bean name="dynaForm" type="org.apache.struts.action.DynaActionForm">
   <form-property name="username" type="java.lang.String" />
   <form-property name="age" type="java.lang.Integer"/>
  </form-bean>
 </form-beans>
 *在Action中使用动态ActionForm,参见DynaActionFormTestAction.java
  DynaActionForm daf = (DynaActionForm)form;
  String username = (String)daf.get("username");
  Integer age = (Integer)daf.get("age");
  
 动态ActionForm其实是把页面中的html元素的名字和值放到了map中,所以通过get方法可以取出相应的值
 动态ActionForm采用EL表达式的输出方式,${dynabean.map.prop}, 参见:dyna_actionform.jsp
 动态Action的验证,通常使用动态验证框架validator

2、采用struts上传文件
 * 页面的配置,如:
  <form action="upload.do" method="post" enctype="multipart/form-data">
    标题:<input type="text" name="title"><br>
    文件:<input type="file" name="myfile"><br>
    <input type="submit" value="http://www.mamicode.com/提交">
   </form>
  * ActionForm中使用FormFile来接收上传的文件,参见:UploadActionForm.java
  * 在Action中调用FormFile取得上传文件数据,采用流输出,即完成上传,参见:UploadTestAction.java
  * 采用<controller/>标签配置上传参数,如:<controller maxFileSize="10M"/>
  
3、空字段测试
 * 在表单中没有input输入域,jsp脚本接收到的值为null,el表达式接收到的值为空串
 * 如果表单中的值,没有输入,那么jsp脚本和el表达式接收到的值都为空串
 
4、测试ActionForm类型的自动转换
 * boolean:yes,1,on,true都会转换成True类型,而且忽略大小写,其他情况转换成false
 * Date类型的转换:
  * 如果是java.sql.Date,页面日期的格式必须为yyyy-mm-dd,才可以转换
  * 如果是java.util.Date,默认情况下struts无法转换

 * 自定义转换器的实现步骤
  * 实现converter接口,实现convert方法
  * 将实现的conerter注册,通常情况采用servlet注册
  * 采用servlet注册需要注意标签的配置,<load-on-startup>10</load-on-startup>(也可以采用struts plugin注册)
  
Struts对ActionForm的自动搜集过程:
  * 将页面数据放到map中,其中map中的key为页面中的名称,map中的value为页面中的value值
  * 调用BeanUtils.setProperties方法,将map中的值逐个设置到ActionForm实例上,对于ActionForm中的每个属性
    根据类型调用相应的Converter,然后调用相应的convert方法,将相应的字符串转换成ActionForm中指定的类型
    
可以通过BeanUtils.copyProperties(目标对象,源对象)方法进行

 

Struts2