struts2的学习总结

                        Struts2学习总结

一、配置文件问题

首先,javaweb项目在运行时首先会查web.xml文档,比如我们直接在服务器上运行某一个项目时,localhost:8080/helloworld会直接运行出该项目的index.jsp页面,那是因为在初始的web.xml文档中有这么一段

<welcome-file-list>

<welcome-file>index.jsp</welcome-file> </welcome-file-list>

我们大体基本可以明白,在xml文档中,默认的欢迎页面就是index.jsp如果不设置这个(当然,这里是默认的)或者将index.jsp的名字改掉,那么服务器就会报错误。

 

 

对于Struts2框架而言,需要加载FilterDispatcher,只要Web应用负责加载FilterDispatcher,FilterDispatcher将会加载Struts2框架。

因为Struts2将核心控制器设计成Filter,而不是一个普通Servlet。故为了让Web应用加载FilterDispatcher,只需要在web.xml文件中配置FilterDispatcher即可。

标准配置文件如下:

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

<web-app id="WebApp_9"version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/j2eehttp://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

 

   <display-name>Struts Blank</display-name>

 

   <filter>

   <!-- 配置Struts2核心Filter的名字 -->

       <filter-name>struts2</filter-name>

       <!-- 配置Struts2核心Filter的实现类 -->

       <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>

         <init-param>

         <!-- 配置Struts2框架默认加载的Action包结构,可以没有。 -->

         <param-name>actionPackages</param-name>

         <param-value>org.apache.struts2.showcase.person</param-value>

         </init-param>

          <!-- 配置Struts2框架的配置提供者类 -->

         <init-param>

         <param-name>configProviders</param-name>

         <param-value>lee.MyConfigurationProvider</param-value>

         </init-param>

   </filter>

<!-- 配置Filter拦截的URL -->

   <filter-mapping>

   <!-- 配置Struts2的核心FilterDispatcher拦截所有用户请求 -->

       <filter-name>struts2</filter-name>

           <!-- /*在这里指的是根目录下所有的请求页面的路径-->

       <url-pattern>/*</url-pattern>

   </filter-mapping>

 

   <welcome-file-list>

       <welcome-file>index.html</welcome-file>

   </welcome-file-list>

</web-app>

有了标准的web.xml文档,我们在部署运行web项目时,服务器先读取web.xml文档,这时通过过滤器所提供的<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>

这样项目就知道,页面所提交的参数和请求都是由Struts2框架所提供的方法来处理,既然由Struts2框架来处理,那么Struts2是否也要有自己独立的xml文档来处理一系列的请求分类呢?

答案是肯定的,我们需要在src文件夹下建立struts.xml 来处理不同的请求

Struts2框架中核心组件就是Action、拦截器等,Struts2框架使用包来管理Action和拦截器等。每个包就是多个Action、多个拦截器、多个拦截器引用的集合。

struts.xml文件中package元素用于定义包配置,每个package元素定义了一个包配置。它的常用属性有:

l name:必填属性,用来指定包的名字。

l extends:可选属性,用来指定该包继承其他包。继承其它包,可以继承其它包中的Action定义、拦截器定义等。

l namespace:可选属性,用来指定该包的命名空间。

<!DOCTYPE struts PUBLIC

        "-//Apache SoftwareFoundation//DTD Struts Configuration 2.0//EN"

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

<struts>

       <!—我们在编写时,需要时时更改代码,并且观察在服务器上的运行效果,这行代码保证了,我们在时时更改时,服务器可以在不重启的情况下可以动态更改执行-->

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

       <!—这行保证的是页面在提交中文时,后台接收不出现乱码-->

    <constantname="struts.i18n.encoding" value="GBK" /> <!--internationalization -->

    <!-- struts2action必须放在一个指定的包空间下定义 -->

    <packagename="default" extends="struts-default" namespace=””>

    <!-- 定义处理请求URLlogin.actionAction -->

        <actionname="login"class="org.qiujy.web.struts.action.LoginAction">

        <!-- 定义处理结果字符串和资源之间的映射关系 -->

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

            <resultname="error">/error.jsp</result>

        </action>

    </package>

</struts>

上面是xml的一个基础配置,当然action只是一个简单的例子。后续会补充xml文档中新出现的常用标签。

 

 

二、Action总结

继承ActionSupport

在使用时需要继承ActionSupport方法,注意excute()的重写,但是也不一定必须使用或者重写该方法,在没使用的方法中要有return SUCCESS,来指定跳转页面

调用Action类时利用DMI(DynamicMethod Invocation)方式使用其方法

具体来看,我们在某一个Action类中写了几个方法,如果按照在xml中一次填写Action的类和方法就会产生大量的action,所以使用动态方法调用时就避开了这种麻烦

  <a href="<%=context %>/user/userAdd">添加用户</a>  
    <br />  

    <ahref="<%=context %>/user/user!add">添加用户</a>  
    <br />  

从上述代码就可以看懂,动态调用将不直接在xml文档中指定被调用Action的method而是转向在jsp页面中根据操作找到指定方法

Struts2中Action接收参数的方法主要有以下三种:
1.使用Action的属性接收参数:
    a.定义:在Action类中定义属性,创建get和set方法;
    b.接收:通过属性接收参数,如:userName;
    c.发送:使用属性名传递参数,如:user1!add?userName=Magci;
2.使用DomainModel接收参数:
    a.定义:定义Model类,在Action中定义Model类的对象(不需要new),创建该对象的get和set方法;
    b.接收:通过对象的属性接收参数,如:user.getUserName();
    c.发送:使用对象的属性传递参数,如:user2!add?user.userName=MGC;
3.使用ModelDriven接收参数:
    a.定义:Action实现ModelDriven泛型接口,定义Model类的对象(必须new),通过getModel方法返回该对象;
    b.接收:通过对象的属性接收参数,如:user.getUserName();
    c.发送:直接使用属性名传递参数,如:user2!add?userName=MGC

通配符问题

在指定命名规则后利用通配符来实现同包下多个类一个action调用

如*_*可以在User_Add类和Manager_Add类可以根据jsp中所写的路径再经过查找对应包下的com.Add.{1}_{2}来对指定类进行操作,这样做也大大减少了action的冗余问题

获取web元素

获取web元素共有四种方法,但实际上常用的IOC原则也叫作依赖注入来获取page所传过来的session、application,request,response。

但是还是粗略的整理一下其他三种获取方式。

1.依赖于容器(ActionContext)获取Map类型的Web元素
2.依赖于容器(ServletActionContext)获取真实类型的Web元素
3.依赖于Struts2框架注入(IoC-控制反转)获取Map类型的Web元素(只用这种方法)
4.依赖于Struts2框架注入(IoC-控制反转)获取真实类型的Web元素(与第三种几乎相同,只是获取的Map元素不再使用,而是直接使用类来获取元素)

第一种方法:依赖于容器(ActionContext)获取Map类型的Web元素

 

 【ActionContext】是Action执行的上下文,提供一系列相关方法用于访问保存在HttpServletRequest、HttpSession、ServletContext中的信息,并将其存储在Map中。
【ActionContext对象获取】 通过ActionConext类的静态方法getContext()
【ActionContext常用方法】
public Object get(String key):获取ActionContext中指定键名的元素对象
public Map<String, Object> getSession():获取session元素对象
public Map<String, Object> getApplication():获取application元素对象
【Map常用方法】
public void put(String key,Object value):向Map对象中添加一个具有键名标识的元素
public Object get(Object key):从Map对象中获取指定的元素

 

 在Action中获取Web元素的方法】
 1.获取ActionContext对象
 ActionContext ac= ActionContext.getContext(); 
 2.通过ActionContext对象获取Map类型的Web元素
 Map<String,Object> s=ac.getSession();
 或:Map<String,Object> s=( Map<String,Object> )ac.get("session");
 3.使用Map对象的put/get方法添加/获取属性
 s.put("username","lucky");
【JSP中获取Web元素属性方法】 
 1.通过JSP脚本元素
 <%=session.getAttribute("username")%>

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

 

demo1.java

ActionContext ac=ActionContext.getContext();

               //ac已经算是获得了request

               ac.put("sse","request获取");

               Map<String,Object>sse=ac.getSession();

               sse.put("sse","session获取");

               Map<String,Object>app=ac.getApplication();

               app.put("sse","applaction获取");

demo1.jsp获取元素之代码

<%="  session内容为:"+session.getAttribute("sse")%><br>

 <%=" aplication内容为:"+application.getAttribute("sse")%><br>

  <%="  request内容为:"+request.getAttribute("sse")%><br>

第二种方法:依赖于容器(ServletActionContext)获取真实类型的Web元素

【问题】 通过ActionContext获取的Web元素是Map形式的,这对于习惯了Servlet编程的开发人员可能不太习惯
【解决方法】Struts2框架中可以通过ServletActionContext类 获取 ServletAPI对象
【ServletActionContext的常用方法】 
 public static HttpServletRequest  getRequest():获取请求对象
 public static ServletContext  getServletContext():获取应用程序对象
【思考】
  获取HttpSession的方法?

 

【基本思路】
  1、在Action中使用真实类型的Web元素,即通过ServletActionContext获取HttpServletRequest、HttpSession、ServletContext类型的Web元素。
  2、在视图中输出Web元素属性的方法不变。

demo2.java

HttpServletRequest request;

               HttpSessionsession;

               ServletContextapplication;

               request=ServletActionContext.getRequest();

               session=request.getSession();

               application=ServletActionContext.getServletContext();

              

               request.setAttribute("sse","request获取");

               session.setAttribute("sse","session获取");

               application.setAttribute("sse","application获取");

demo2.jspdemo1.jsp一样

 

第三种方法:依赖于Struts2框架注入(IoC-控制反转)获取Map类型的Web元素(只用这种方法

相关概念】
 DI:DependencyInjection—依赖注入
 IoC:Inversion ofControl—控制反转
  两个概念表达相同的思想,即:
     当我们想得到某个对象时,不需要我们主动创建这个对象,或主动去获取这个对象,而是等待系统把这个对象自动交给我们,我们只是被动接受。(网购模式)
     我们需要的对象我们不去主动创建,而让系统自动填充的,叫依赖注入;本来是我们控制去获取这个对象,结果控制权交给了系统,我们被动接受,叫控制反转。

 

【依赖注入的相关接口】
  Action中通过实现相关接口,Web元素即可由框架自动注入,这组接口以Aware(知道,明白)结尾
  RequestAware:Map类型的request元素
  ServletRequestAware:HttpServletRequest类型
  ServletResponseAware:HttpServletResponse类型
  SessionAware:Map类型的session元素
  ApplicationAware:Map类型的application元素
  CookiesAware:Map类型的Cookie元素

 

 

【依赖注入的Web元素获取方法】
 1.创建Action时实现Web元素相关接口
 2.在Action中声明Map类型的私有变量
 3.在Aware接口的实现方法中为变量赋值

 

【基本思路】
  1、创建Action实现RequestAware、SessionAware、ApplicationAware三个接口,声明三个Map类型的私有变量,三个接口的实现方法分别对三个变量赋值,从页获取Web元素。
  2、在视图中输出Web元素属性的方法不变。

demo3.java

public class demo1 extends ActionSupportimplements RequestAware,SessionAware,ApplicationAware {

        privateString name,password;//变量名可以与form表单中的name一致,也可以不一致,但是setget方法后的变量必须与form表单中的保持一致

        Map<String,Object>request;

        Map<String,Object>session;

        Map<String,Object>application;

        publicString execute() throws Exception {

               this.name="demo1获取参数Action参数的第一种方法:基本数据类型的自动填充";

               request.put("sse","request获取");

               session.put("sse","session获取");

               application.put("sse","application获三");

              

               returnsuper.execute();

        }

        publicString getUsername() {

               returnname;

        }

        publicvoid setUsername(String username) {

               this.name= username;

        }

        publicString getPassword() {

               returnpassword;

        }

        publicvoid setPassword(String password) {

               this.password= password;

        }

        publicvoid setRequest(Map<String, Object> request) {

               this.request=request;

        }

publicvoid setApplication(Map<String, Object> application) {      

       this.application=application;

        }

        publicvoid setSession(Map<String, Object> session) {

               this.session=session;

              

        }

}

利用include方法来调用其他xml中的action(主要用于模块开发下的整合)

例:

login.xml

<struts>

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

        <action name="login*"class="com.bjsxt.struts2.user.action.LoginAction{1}">

           <result>/user_login_success.jsp</result>

        </action>

    </package>

</struts>

struts.xml

<struts>

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

    <include file="login.xml"/>

</struts>

这样就可以将login.xml中的action归纳到struts.xml中使用。

DefaultAction的使用

在大部分网站中,即使用户操作错误也很少直接报404错误,而是已更友好的界面来提示,那么来说需要一个DefaultAction来处理,将未知的指令利用这个action来指向一个交互界面。

 

Result总结(入门级别)

Result中的type

Result中默认的类型是Dispatcher,这个就不详细说了。就是通过Action找到指定的jsp(只能跳转到页面,不适用于Action或者Servlet),但是常用的类型共有四种,其中最常用的有两种

  1. redirect:action处理完后重定向到一个视图资源(如:jsp页面(只适用于页面,不适用于Action或者Servle)),请求参数全部丢失,action处理结果也全部丢失,页面重新将资源发送到被重定向的页面。
  2. redirect-action:action处理完后重定向到一个action,请求参数全部丢失,action处理结果也全部丢失。
  3. chain:action处理完后转发到一个action,请求参数全部丢失,action处理结果不会丢失

具体的应用可以参考以下代码

<struts>

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

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

   <action name="r1">

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

   </action>

   <action name="r2">

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

   </action>

   <action name="r3">

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

   </action>

   <action name="r4">

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

   </action>

    </package>

</struts>

根据上面的xml建立页面后尝试跳转并观察跳转后url路径基本上就明白各自的含义了。

streamfreemark会后续跟进学习

global-result(全局result)

当某个页面或者action为每一个Action都可能访问到的时候,我们不需要在每一个人Action下面建立该result,只需要建立一个全局result就可以了

<global-results>

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

</global-results>

当多个或者所有Action都会访问mainpage时,所以建立全局result可以减少xml中代码冗余。

那么如果我们想在别的package下调用别的package中的全局result该怎么办呢?

<packagename="admin" namespace="/admin" extends="user">

           <action name="admin"class="com.bjsxt.struts2.user.action.AdminAction">

                  <result>/admin.jsp</result>

           </action>

</package>

从上面的代码我们可以看到,extends终于被使用了,不再是我们以前一直默认的struts-default,而是继承了user这个package,那么该package下的所有action和result都可以为我所用了。

从上述的继承中我们可以学到,如果多个package互相继承某种特定的result时,我们就可以选择将特定的result或者Action拿出来放在单独的pack中,这样所有的package都去继承,就有效的避免了继承错乱和代码冗余。

动态结果集(用的不多,了解即可

根据Action中方法的执行来确定要跳转的jsp或者action

@Override

       publicString execute() throws Exception {

              if(type== 1) r="/user_success.jsp";

              elseif (type == 2) r="/user_error.jsp";

              return"success";

       }

我在action中这样重写execute()方法,其中r是这个类里面的一个成员变量,那么我根据传进来不同的参数,来动态的给r赋值为所要跳转的jsp页面。那么我只需在struts.xml中这样去取得Action中的这个属性,去动态的获取所要跳转的路径

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

                  <result>${r}</result>

           </action>

我们可以看到利用${r}取出相应的参数值即可。也就是从Action的值栈中取值,不是EL表达式,而是OGNL表达式(这样不就写死在java之中,如果页面名字改了的话不就需要改动固定代码吗?为什么要这样,即使多在xml文档中配点也无所谓,最起码以后要改的时候改文档就可以,java类可以避免改动

带参数的结果集

 

首先,我们先看看上面的图并结合下面的代码来看,当client向后台提交一个request请求,并且传入一个参数

<ol>

       <li><ahref="user/user?type=1">传参数</a></li>

</ol>

再到struts.xml中去找user这个namespace下找到user这个Action并且指定type=1

<packagename="user" namespace="/user" extends="struts-default">

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

                  <resulttype="redirect">/user_success.jsp?t=${type}</result>

           </action>    

</package>

下面放上Action的代码

packagecom.bjsxt.struts2.user.action;

 

importcom.opensymphony.xwork2.ActionSupport;

 

public classUserAction extends ActionSupport {

       privateint type;

      

       publicint getType() {

              returntype;

       }

 

       publicvoid setType(int type) {

              this.type= type;

       }

 

       @Override

       publicString execute() throws Exception {

              return"success";

       }

 

}

 

我们再回看上面的那幅图,当Action通过dispatcher来forward指定的page时,Action接收到的参数会存在值栈里面,利用<s:debug></s:debug>我们来看一下会有什么样的结果,这里就不截取运行图了,直接说结果,在valuestack中type中的值为传入值,那么:当使用dispatcher或者chain来跳转到相应的jsp页面时,值栈中的属性是公用的,也可以理解为,在一次Client发起的一次request中值栈的值共用且不清空

而我们的例子里面,在xml中result的type是redirect也就是重定向到一个页面,来,继续回看上图,Client向userAction发起一个request,找到这个Action,type值也成功传入,但是result的type为redirect,直接告诉Client:“接下来你需要新建一个request,并发送给user_success.jsp,参数t=${type}值”,假设我们继续按照上面从值栈取值<s:propertyvalue="t"/><br/>会得到什么结果呢?答案很容易知道,肯定取不出来东西。当新的request再次发起请求的时候,值栈已经被清空了,这时候再去取必然取不到,

 

那么该如何取到重定向过来的值呢?利用这个方法<s:property value="#parameters.t"/>我们不去值栈里面取,而是去actioncontext里面以属性的方式给取出来。

好了综上,当我们在Action中想要跳转页面,其实总共分两个大类,一种是一个request,那么值栈被共享只需要到值栈中取到相应的值就可以了,另一种就是重定向的方式来传值,也就是一个Action返回带参数的结果集时被重定向到另一个Action或者jsp页面中去,值栈被清空,那就需要到stackContext中去取得参数。

有些特殊情下,需要在JSP<%%>java代码段中直接访问值栈内容。而不使用<ww:propertyvalue="name"/>获取,可以通过如下方式进行:

String name =(String)ActionContext.getContext().getValueStack().findValue("name");

为了正常运行,还需要在jsp将这com.opensymphony.xwork.ActionContext 类引入

<%@ page import="com.opensymphony.xwork.ActionContext" %>

 

Struts2在下载文件时result需要配置的东西

当result为stream类型时,struts2会自动根据你配置好的参数下载文件。

其中主要使用的参数是:
contentType 指定下载文件的文件类型 —— application/octet-stream 表示无限制
inputName 流对象名 ——比如这里写inputStream,它就会自动去找Action中的getInputStream方法。
contentDisposition 使用经过转码的文件名作为下载文件名—— 默认格式是attachment;filename="${fileName}",将调用该Action中的getFileName方法。
bufferSize 下载文件的缓冲大小

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值