struts2学习笔记

.struts2(2.1)知识基础部分

Ø  1 .struts2概述

Action、基本数据验证、Result、常用的配置文件、OGNL和ValueStack、Struts2 Tags

类型转换、上传下载、防止重复提交、Interceptor(拦截器)、MVC设计思想、Struts2基于webWork

Ø  2 .Action相关内容

<1>action入门    <2>namespace

<3>自定义Action  <4>路径设置

<5>调用action中定义的方法

<6>通配符  <7>接受用户输入的3中方式

<8>乱码问题解决 <9>简单的数据校验 <10>aciton中访问web元素

<11>包含模块的文件 <12>默认的action

Ø  3 .struts2入门

ü  构建项目

<1>整合jar

需要的核心jar包freemarker-2.3.13 、ognl-2.6.11、 struts2-core-2.1.6、xwork-2.1.2

       <2>增加struts2的核心过滤器

Web.xml中增加如下内容:

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

其中StrutsPrepareAndExecuteFilter包含两个过滤器

<3>增加struts2的配置文件

Struts.xml放到根目录下内容如下:

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

<!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"

    "http://struts.apache.org/dtds/struts-2.1.dtd">

<struts>

     <constant name="struts.devMode" value="true"></constant>

      <package name="front" namespace="/struts2test" extends="struts-default" >

      <action name="hello">

            <result>/page/hello.jsp</result>

       </action>

    </package>

</struts>

以上例子用没有实际的action类,而是中间转发过程

访问此程序地址为:http://localhost:9080/struts2_001/struts2test/hello

访问规则为地址+命名包空间名称+action的名称

ü  常用小技巧

<1>struts2.xml配置开发模式,使的修改配置文件之后不用重新启动,访问直接生效

配置strtus2常量

<constant name="struts.devMode" value="true"></constant>

<2>查看jar对应的源码

在eclipse中切换到package查看模式,选中查看的包,右击属性

可以绑定到特定的项目空间(workspace)、特定的文件、特定的文件夹;

 

绑定到源代码文件夹,之后遍可以直接访问源码;

<3>绑定java doc可以查看api文档

查看方式,选种类或方法之后F1后,可以查看api文档

 

 

 

 

Ø  4 .struts2工作机制

Struts2.xml中的package元素的namespace元素和访问路径一一对应的

访问路径中的后缀名action可以进行省略

 

Ø  5 .namespace元素

ü  Namesapce的作用

 

ü  详解说明

<package name="firstTest" namespace="/" extends="struts-default">

    <action name="helloAction">

        <result>/page/hello.jsp</result>

    </action>

</package>

 

  1. A.   package包含三个属性namenamespaceextendspackage作用是为了防止重复(类似于java中的包的作用);
  2. B.        action:必须增加name属性,可以增加具体实现class属性
  3. C.       result可以添加name属性以及对应值,不增加此属性,默认为success(具体值可以在action中进行转发定义)
  4. D.       namespace默认为空(namespace=””),可以访问任何一个action(匹配的),任何对应的路径(namespace 下)的action都可以访问

copy项目的时候,由于webContext还是原来定义的名字,进行如下修改

项目右击属性web配置,对项目的访问上下文进行修改

 

 

Ø  6 .action

ü  核心内容

action控制视图的转向,可以自己定义action,action可以是一个普通的类,只要类中有方法execute即可

 

统一修改jsp中代码的编码方式

 

<package name="firstTest" namespace="" extends="struts-default">

    <action name="hello" class="com.action.HelloAction">

        <result>/page/hello.jsp</result>

    </action>

 </package>

不配置action的class属性值的时候,默认使用了ActionSupport类

编写action的三种方式

<1>Action可以实现action接口

<2>继承ActionSupport(用此种)

<3>可以是普通的java类,必须包含execute方法

Action实现视图转发的类都是返回字符串数据,和具体result中的属性name对应

Ø  7 .路径(path)问题

在页面中链接(<a href=”index.jsp”>index.jsp<a>)以及提交到某一地址,由于struts2中运用了namespace概念,访问任意地址,都先便利struts2.xml中的namespace信息,如果找不到对应的命名空间信息,会链接到非预期的地址,为了访问具体地址,一般用绝对路径解决此问题

 

通常struts2访问的原理,首先请求信息寻找(web.xml),之后通过过滤器,进行请求转发

,过滤器读取配置问题struts2.xml,根据namespace和action具体具体转发的action类,如果找寻不到

具体的namepace和action,则请求转发给web容器进行处理

具体访问路径可以根据服务器信息进行绝对定位,struts2的访问路径是根据action的请求地址,而不是jsp的地址进行

请求转发,对于jsp的路径尽量使用如下方式

String path = request.getContextPath();

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

url:basePath+path+jspname;

String path = request.getContextPath();

String basePath

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

<a href="<%=basePath %>page/index.jsp">index.jsp</a>

 

Ø  8 . 动态方法调用

action执行的时候,默认执行execute方法,但可以自己定义方法

<1>方式1:

配置文件中增加method属性,可以提供给请求转发进行调用,可以配置参数method属性

在配置文件struts2.xml中配置信息如下

<package name="user" namespace="user" extends="struts-default">

       <action name="userAction" class="actionClassPath" method="methodName">

              <result name="adduser">/page/useradd.jsp</action>

       </action>

</package>

缺点:如果存在多个方法(add,delete,update,query),每个方法都需要单独配置一个action块

,不推荐使用

<2>方式2(建议使用):动态方法调用(dmi dynamic method invoke)

在配置文件struts2.xml中,不用配置属性method,只需要配置一个action,请求调用时候直接动态调用

(不同的方法,各自需要返回自己的视图,需要配置多个result)

<package name="user" namespace="user" extends="struts-default">

       <action name="userAction" class="actionClassPath">

              <result name="adduser">/page/useradd.jsp</action>

              <result name="deleteuser">/page/userdelete.jsp</action>

              <result name="updateuser">/page/userupdate.jsp</action>

       </action>

</package>

请求地址格式为:basePath+path+namespace/+action!methodName;

 

Ø  9.请求action的地址通配符形式

利用*通配符号,并且结合参数占位符{1}{2}.....

约定优于配置(提前约定好jsp页面以及action中方法的命名规则),用通用的配置,匹配所有的路径调用信息

<package name="user" namespace="/user" extends="struts-default">

              <action name="user*" class="com.action.UserAction" method="{1}">

                     <result name="{1}_page">/page/user.jsp</result>

                     <result name="{1}_user">/page/user.jsp</result>

                     <result name="{1}_user">/page/user.jsp</result>

              </action>

       </package>

{1}代表第一个*

{2}代表第二个*

Ø  10.action接受请求参数

注意请求地址中的namespace前不用增加"/"(action="namespace/actionname!methodname")

action中有三种接受参数值的方式

<1>属性接受(普通属性,基本类型的参数和复合类型的参数)

   数组和基本属性相同增加setter和getter方法

   注意:基本类型的数据必须提供setter和getter方法

   对Map类型的数据,只要提供getter方法就可以(struts2内部调用的是Map的put方法)

   struts2的action接受属性值是对应的getName中的Name并不是属性的值

   在action中增加属性定义字段,并且增加对应的setter和getter方法

   如下:

   1)action中增加属性

  public class UserAction extends ActionSupport{

              private String userName;

              private String password;

              public String add(){

              System.out.println("add_page");

              return "add_page";

              }

              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)form表单地址

       <form name="userForm" method="post" action="user/user!add">

       username:<input name="userName" type="text"/>

       password:<input name="password" type="text"/>

    <input type="submit"  name="sb"  value="submit"/>

</form>

 <3>调试属性信息,通过调试信息可以很对定位读取属性的信息

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

 <s:property value="userName"/>

 <s:debug></s:debug> 调试信息

<2>domainModel域模型接受参数

将属性封装到vo(pojo)中,之后在action进行引用

 不用new vo,struts2已经对vo进行了对象初始化

 并在vo提供对应属性的setter和getter方法

 在表单属性的名称需要引用vo的名称

 user.userName

 user.password

 如下:

 1)定义action并引用User

 public class UserAction extends ActionSupport{

       private User user;  

       public User getUser() {

              return user;

       }

       public void setUser(User user) {

              this.user = user;

       }

       public String add(){

              System.out.println("add_page");

              return "add_page";

       }

 2)表单元素名称定义

 <form name="userForm" method="post" action="user/user!add">---注意地址访问信息中命名空间

       username:<input name="user.userName" type="text"/>

       password:<input name="user.password" type="text"/>

    <input type="submit"  name="sb"  value="submit"/>

</form>

 3)获得属性的值

      <s:property value="user.userName"/>

    <s:property value="user.password"/>

   <s:debug></s:debug>

 

<3>ModelDriven(模型驱动)接受属性参数(这种方式不常用)

   action实现接口ModelDriven<T>,且实现getModel方法

   此时引用vo必须进行new

   如下:

   1)action内容

   public class UserAction extends ActionSupport implements ModelDriven<User>{

       private User user = new User();   

       public String add(){

              System.out.println("add_page");

              return "add_page";

       }

       public User getModel() {

              return user;

       }

}    

  2)请求页面参数名称

  <form name="userForm" method="post" action="user/user!add">

       username:<input name="userName" type="text"/>

       password:<input name="password" type="text"/>

    <input type="submit"  name="sb"  value="submit"/>

       </form>

       3)读取参数的值进行显示

       <s:property value="userName"/>

    <s:property value="password"/>

     <s:debug></s:debug>

 

Ø  11.中文乱码

Struts2.xml文件中新增配置属性

<constant name=”struts.i18n.encoding” encode=”GBK”/>

 在struts2中如果在版本2.1中利用新的filter即

org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

即使增加编码配置方式,对于汉字也是乱码

可以换回原来的过滤器

org.apache.struts2.dispatcher.FilterDispatcher

汉字的乱码问题就解决了

Ø  12.简单的数据校验

<1>简单介绍

ActionSupport中的方法addFieldError和标签<s:fielderror fieldName=””/>进行简单的数据校验

实际上errors的校验的信息在Map中

如下:

public class UserAction extends ActionSupport{

    private String userName;

    public String add(){

           System.out.println("userName:"+userName);

       if(!this.userName.equals("wuoguoqing")){

           this.addFieldError("userName", "输入信息错误");

       }

       return "add_user";

    }

    public String getUserName() {

       return userName;

    }

    public void setUserName(String userName) {

       this.userName = userName;

    }

}

页面

<s:fielderror fieldName="userName" theme="simple"/>

  <s:property value="errors.userName"/>

 <s:debug></s:debug>

有关错误调试以及ValueStack信息

<s:debug></s:debug>用于显示页面中的值栈中的信息

 

<2>可以对同一个字段指定多个错误信息

if(!this.userName.equals("wuoguoqing")){

           this.addFieldError("userName", "输入信息错误1");

           this.addFieldError("userName", "输入信息错误2");

           this.addFieldError("userName", "输入信息错误3");

           this.addFieldError("userName", "输入信息错误4");

           return  "add_user";

       }

Ø  13.action访问web页面中的元素

action中如何web元素对象request,session,application中的内容

通常有四种方式ActionContext(Map),(RequestAware、SessionAware、ApplicationAware)、ServletActionContext、ServletRequestAware

<1>ActionContext方式

通过ActionContext对象获得web元素对象的内容,

ActionContext封转了web元素存储访问的功能

通过Map进行访问,并且struts2可以将Map中的内容映射成HttpServletRequest中的内容,可以在页面中

直接通过jsp方式进行访问(request.getAttribute()),这种方式依赖于容器中的ActionContext,ActionContext并不是

单例形式,内部通过ThreadLocal实现

如下:

public class UserAction extends ActionSupport {

       private Map request;

       private Map session;

       private Map application;

       public UserAction(){

              request= (Map)ActionContext.getContext().get("request");

              session= (Map)ActionContext.getContext().getSession();

              application= (Map)ActionContext.getContext().getApplication();

       }

      

       public String add(){

           request.put("rusername","username");

           session.put("susername","susername");

           application.put("ausername","ausername");

              System.out.println("add_page");

              return "add_page";

       }

      

}

将web元素的内容通过jsp或ognl方式进行访问显示

<%=request.getAttribute("rusername")%>

<s:property value="#request.rusername"/>

<2>实现对应接口(RequestAware、SessionAware、ApplicationAware由struts2提供)

在调用Action类的时候,先检查此action是否实现了上述接口,如果实现了调用对应的

setter方法,实例化web元素,由struts2实现

Aware:得知、知道

实现对应接口就知道对应web元素中的内容了

如下:

对初始化工作request/session/application由容器实现(DI dependcy injection)

public class UserAction extends ActionSupport implements RequestAware,

              SessionAware, ApplicationAware {

       private Map<String, Object> request;

       private Map<String, Object> session;

       private Map<String, Object> application;

 

       public String add() {

              request.put("rusername", "username");

              session.put("susername", "susername");

              application.put("ausername", "ausername");

              System.out.println("add_page");

              return "add_page";

       }

       public void setRequest(Map<String, Object> arg0) {

              this.request = arg0;

       }

       public void setSession(Map<String, Object> arg0) {

              this.session = arg0;

       }

       public void setApplication(Map<String, Object> arg0) {

              this.application = arg0;

       }

}

 

<3>通过ServletActionContext获得对应的web元素的内容

import javax.servlet.ServletContext;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

 

public class UserAction extends ActionSupport {

       private HttpServletRequest request;

       private HttpSession session;

       private ServletContext application;

       public UserAction(){

              request = ServletActionContext.getRequest();

              session = request.getSession();

              application = session.getServletContext();

       }

       public String add() {

              request.setAttribute("rusername", "rusername");

              System.out.println("add_page");

              return "add_page";

       }

}

<4>实现ServletRequestAware接口

   如下:

   public class UserAction extends ActionSupport implements ServletRequestAware {

       private HttpServletRequest request;

       private HttpSession session;

       private ServletContext application;

       public String add() {

              System.out.println("add_page");

              return "add_page";

       }

       public void setServletRequest(HttpServletRequest arg0) {

       this.request = arg0;

       this.session=this.request.getSession();

       this.application = this.session.getServletContext();

             

       }

}

Ø  14.配置文件中包含模块配置文件(struts2.xml)

此中方式可以根据模块划分,将配置文件进行分块规划

<struts>

       <constant name="struts.devMode" value="true"></constant>

       <include file="user.xml"></include>

       <package name="user" namespace="/user" extends="struts-default">

              <action name="user" class="com.action.UserAction">

                     <result name="add_page">/page/user.jsp</result>

              </action>

       </package>

</struts>

 

Ø  15.默认action(默认定位访问那个页面,访问不存在的就调转到指定页面)

<package name="default" namespace="/" extends="struts-default">

              <default-action-ref name="index">

                     <result>/page/user.jsp</result>

              </default-action-ref>

</package>

Action总结

 

Ø  16.Result的配置

result的类型:

如果result如果不指定类型(type),默认为dispather(只能跳转到页面)

常用的包含:

dispatcher、redirect、chain、rediectAction

freemarker、stream、velocity......

<1>dispatcher:默认result使用此种方式(地址显示action的地址信息)

<2>redirect:客户端跳转(地址显示jsp)

<3>redirectAction:直接跳转到另一个action

<4>chain:从可以action直接跳转到另一个action

注意chain跳转到其他package下的action中

配置如下:

<action  name="r3">

       <result  type="chain">

       <param name="actionName">actionname</param><!--指定action的名字-->

       <param name="namespace">namespace</param><!--指定namespace的名字-->

       </result>

</action>

 

<package name="default" namespace="/" extends="struts-default">

              <default-action-ref name="index" >

              </default-action-ref>

              <action name="index">

                     <result>/index.jsp</result>

              </action>

              <global-results>

                     <result name="mainpage">/index.jsp</result>

              </global-results>

       </package>

      

       <package name="result" namespace="/result"  extends="struts-default">

              <action name="r1">

                     <result type="dispatcher">/page/r1.jsp</result>

              </action>

              <action  name="r2">

                     <result  type="redirect">/page/r2.jsp</result>

              </action>

              <action  name="r3">

                     <result type="chain">r1</result>

              </action>

              <action  name="r4">

                     <result  type="redirectAction">r2</result>

              </action>

       </package>

Ø  17.全局结果集(Globals_Result)

一般用于维护公共的结果集合,其他包中若使用此结果集可以通过extends集成实现(如错误页面、主页面)

在同一个包中(struts2.xml中package)中,如果多个action公用相同的结果集,可以将公用的result写入到

<global-results>元素中如:

<global-results>

       <result name="mainpage">/index.jsp</result>

</global-results>

同一包级下的action可以使用定义的globalresult

如果不在同一个包中,可以在包元素中使用extends属性使用其他包中的全局结果集

Ø  18.动态结果集

action中根据传递的参数,动态确定放回结果集的信息

如下:

public class DynamicAction extends ActionSupport implements ServletRequestAware  {

       private HttpServletRequest request;

       private String type;

       private String url;

       public String getUrl() {

              return url;

       }

       public void setUrl(String url) {

              this.url = url;

       }

       public String getType() {

              return type;

       }

       public void setType(String type) {

              this.type = type;

       }

       public void setServletRequest(HttpServletRequest arg0) {

              this.request=arg0;

       }

       public String execute(){

              System.out.println("type:"+type);

              if("1".equals(type)){

                     url="/page/r1.jsp";

              }else{

                     url="/page/r2.jsp";

              }

             

              return "sucess";

       }

配置文件如下:

<package name="dynamic" namespace="/dynamic" extends="default">

<action name="dynamic" class="com.action.DynamicAction">

<result name="sucess">${url}</result>

</action>

</package>

Ø  19.L(Object Graph navigation language)

Action中调用ServletActionContext获得Request

 

每一个特定的Action都有一个对应的ValueStack,struts2把相关action的属性信息存入其中,

以供页面或其他程序中调用

 

ü  访问对象的属性(普通属性

注意:

如果要访问action中定义的属性以及对象并在jsp运用ognl表达式进行显示,

在action中的属性以及对象必须设置setter/getter,这样struts2才会把相应的属性以及对象存放在action的栈中,页面才能进行数据访问

public class UserAction extends ActionSupport {

    private String name;

    private String password;

    private User user = new User();

    private List<User> list  = new ArrayList<User>();

。。。。。。setter/getter

}

userName:<s:property value="name"/><br/>

  password:<s:property value="password"/><br/>

  user:<s:property value="user.userName"/><br/>

  user static method:<s:property value="@com.vo.User@say()"/><br/>

  <s:property value="'<hr/><hr/>'" escape="false"/>

  List:<br>

  <s:property value="list.get(0).userName"/><br/>

  <s:property value="list.size()"/>

 

 

<1>访问valueStack中的普通属性

public class UserAction extends ActionSupport {

    private String userName;

    private String password;

。。。。。。

}

页面直接访问属性的值

<s:property value="userName"/><br/>

<s:property value="password"/><br/>

<2>访问valueStack中的vo

 

一般情况下action中vo可以不进行new(地址中传递vo.attribute,struts2会自动创建vo对象,否则的需要自己创建,如地址信息中传递user.name=nm&&user.pwd=p,自动构建user对象),也可以直接new一个vo对象

public class UserAction extends ActionSupport {

    private User user;

    private User user = new User();

。。。。。。

}

页面中访问对象的属性值

<s:property value="user.name"/><br/>

    <s:property value="user.pwd"/><br/>

<3>ognl对象图导航语言

传值cat.friend.name=nm

通过此种语言可以对聚合对象进行导航,以便访问对象中的属性

 

<s:property  value="cat.friend.name"/>

即访问对象的属性

vo.vo1….attibute

ü  访问对象的方法(普通方法)

可以访问action的普通方法

或访问action中属性(对象)的基本方法

 

<s:property value="user.pwd.length()"/><br/>

<s:property value="cat.say()”/>//对象中的方法

<s:property value="method()”/> //action中普通方法

 

ü  访问对象静态方法

<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>

格式@静态类@静态方法()

格式@静态类@静态属性

ü  访问普通对象的构造方法

<s:property value="new com.vo.User()"/><br/>

ü  访问集合属性的内容

 

 

 

Ø  20.struts-tags

通用标签、控制标签、UI标签

 

ü  <1>通用标签

l  property标签

 

有关property的说明:

<s:property value=”objectName”/>访问valuestack中的objectName对象的值(通过ognl表达式)

<s:property value=”‘stringconstant’e”/>直接显示字符串的值

如果增加default属性,相当于如果栈中存在对应的对象,就显示默认值

l  set标签

相关属性var/name scope,name属性高级版本已经去掉

<1><s:set var=”varname”  value=”object”/>

设置一个变量var,并给予赋值object(此处为对象类型,可以通过ognl表达式进行访问)

 如果不指定存贮范围,默认存贮在request中

 可以通过#varname对变量的内容(从ActionContext)进行访问

<s:set var="param"  value="user"></s:set>

<s:property  value="#param"/>

<%=request.getAttribute("param") %>

<2>设定范围

<s:set var="param"  value="user" scope=”page”></s:set>

设定范围后,通过#paraname无法访问,指定在指定范围内进行范围才可以

<s:set var="pageparam"  value="'reeerwwerwererwr'" scope="session"></s:set><br>

<s:debug></s:debug>

<s:property value="#session.pageparam"/>

注意:<s:debug/>标签可以嵌套在其他标签中(其他标签之下,查看当前标签的在栈中的内容),指定valueStack的调试范围

l  bean标签

引入对象,存放到ActionContext中,以供调用

<s:property value="%{setvalue}"/>

%{setvalue} 表示强制将setvalue作为ognl表达式访问,而不是作为字符串处理

一般标签只要设置了var相当于在valuestack中建立了对应的对象以及内容

在整个页面的任何位置都可以进行访问(ActionContext)

<s:bean name="com.vo.User" var ="users">

    <s:param name="userName" value="'ppppppuser'"></s:param>

//给User对象设置属性值

</s:bean>

<s:property value="#users.userName"/>

<s:debug></s:debug>

可以利用#objectName访问valuestack中的对象

l  include标签

<s:include value=”/config/sss.jsp”/>

l  fielderror标签

 

<s:fielderror fieldName="struts.errorname" theme="simple"></s:fielderror>

l  if标签

<s:set var="count"  value="'12'"></s:set>

<s:if test="count>1">

    very big

</s:if>

<s:elseif test="count>13">

veryvery big

</s:elseif>

<s:else>

very

</s:else>

注意:test中的对象的类型,如果是数值的话如何比较

 

posted @ 2015-03-11 16:32  whokuoking  阅读(174)  评论(0编辑  收藏  举报