struts2学习笔记三

1.1 Struts2中的拦截器

1.1.1 Struts2的拦截器

Struts2 拦截器在访问某个 Action 方法之前或之后实施拦截, Struts2 拦截器是可插拔的, 拦截器是 AOP 的一种实现.

 

1.1.2 Struts2的执行原理:

 

1.1.3 自定义拦截器:

登录的案例:

* 数据封装:

* 数据校验:

* 国际化信息:

* 拦截器:

 

编写拦截器:

* 实现Interceptor接口或者继承AbstractInterceptor

* 重写intercept方法.

 

注册拦截器:

* 两种方式:

1.配置拦截器:

<interceptors>

<!-- 定义拦截器 -->

<interceptor name="privilege" class="cn.itcast.interceptor.PrivilegeInterceptor"/>

</interceptors>

 

<action>中指定使用那些拦截器:

<action name="book_*" class="cn.itcast.action.BookAction" method="{1}">

<result name="input">/jsp/login.jsp</result>

<!-- 使用拦截器 -->

<!-- 使用自定义的拦截器之后,Struts2中的默认拦截器栈就不执行了. 必须手动的执行默认拦截器栈.-->

<interceptor-ref name="defaultStack"/>

<interceptor-ref name="privilege"/>

</action>

 

2.配置拦截器栈:

<interceptors>

<!-- 定义拦截器 -->

<interceptor name="privilege" class="cn.itcast.interceptor.PrivilegeInterceptor"/>

<!-- 定义拦截器栈 -->

<interceptor-stack name="myStack">

<interceptor-ref name="defaultStack"/>

<interceptor-ref name="privilege"/>

</interceptor-stack>

</interceptors>

 

<action>的标签中引用自定义的拦截器栈:

<action name="book_*" class="cn.itcast.action.BookAction" method="{1}">

<result name="input">/jsp/login.jsp</result>

<!-- 引用自定义的拦截器栈就可以了  -->

<interceptor-ref name="myStack"/>

</action>

 

1.2 Struts2文件上传

1.2.1 文件上传原理:

文件上传:将客户端本地文件 写 到服务器上.

 

文件上传的组件:

* JSPSmartUpload:适用Model1阶段,适用在JSP+JavaBean年代.

* FileUpload:Apache下的,文件上传的组件.

* Servlet3.0:完成文件的上传.

* Struts2:完成文件的上传.

 

文件上传必要的条件:

* 1.请求的方式需要是POST.

* 2.表单的表单项中需要<input type=file>文件项,而且文件项需要有name属性,name属性必须有值

* <input type=file name=upload>

* 3.表单的enctype属性需要是multipart/form-data

 

1.2.2 Struts2中的文件上传:

页面中:

<h1>文件上传</h1>

<form action="${ pageContext.request.contextPath }/upload.action" method="post" enctype="multipart/form-data">

文件上传:<input type="file" name="upload"><br/>

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

</form>

 

Action中如何进行接收:

* 只需要在Action,提供三个属性,属性的名称需要跟页面的文件项的name属性有关:

* 提供一个文件类型的属性:用于接收上传文件.

* private File upload;     

* 提供一个字符串类型的属性:用于接收上传的文件类型.

* private String uploadContentType;

* 提供一个字符串类型的属性:用于接收上传的文件名称.

* private String uploadFileName;

 

1.2.3 文件上传过程中的错误处理:

* 上传一个超过2MB的文件

1.配置INPUT逻辑视图:

2.JSP中使用<s:actionerror/>回显错误信息.

* Request exceeded allowed size limit! Max size allowed is: 2,097,152 but request was: 68,800,543!---文件大小超过限制.

3.文件大小的设置在常量中:

struts.multipart.parser=jakarta----Struts2底层解析文件上传使用解析器.

struts.multipart.saveDir=----文件上传过程中产生临时文件,临时文件存放的路径.

struts.multipart.maxSize=2097152----文件上传的总大小.

 

文件上传的功能是由谁完成的?----拦截器.

<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>

 

查看拦截器的源代码:

* 拦截器中提供了一些属性:

* 设置文件上传的大小:

public void setMaximumSize(Long maximumSize) {

        this.maximumSize = maximumSize;

    }

* 设置文件上传文件的类型:

public void setAllowedTypes(String allowedTypes) {

    allowedTypesSet = TextParseUtil.commaDelimitedStringToSet(allowedTypes);

}

* 设置文件上传文件的扩展名:

public void setAllowedExtensions(String allowedExtensions) {

        allowedExtensionsSet = TextParseUtil.commaDelimitedStringToSet(allowedExtensions);

    }

 

* struts.xml中配置fileUpload拦截器的参数:

<action name="upload" class="cn.itcast.action.demo1.UploadAction">

<result name="input">/demo1/upload.jsp</result>

<!-- 引用fileUpload拦截器 -->

<interceptor-ref name="defaultStack">

<param name="fileUpload.maximumSize">2097152</param>

<param name="fileUpload.allowedExtensions">.doc,.jpg</param>

</interceptor-ref>

</action>

 

多文件上传:

提供三个属性的数组:

private File[] upload;

private String[] uploadContentType;

private String[] uploadFileName;

 

 

1.3 文件的下载:

1.3.1 文件的下载:

文件的下载:将服务器上的文件 传输 到客户端.

 

文件下载:

* 1.超链接形式:

* 2.编码的方式:

* 设置两个头和一个流:

* Content-Type:文件的MIME的类型

* Content-Disposition:浏览器支持该格式的文件,以下载形式提供下载.

* 提供一个文件的输入流:输出流的是固定的response.getOutputStream();

 

 

1.3.2 Struts2中的文件的下载:

* 结果页面类型

<result name=”” type=””>

* type:

* stream:----用来做文件的下载.    

 

* struts.xml中进行配置:

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

<action name="download" class="cn.itcast.action.demo2.DownloadAction">

<result name="success" type="stream">

<!-- 基于值栈结构: -->

<param name="contentType">${contentType}</param>

<param name="contentDisposition">attachment;filename=${fileName}</param>

<!-- <param name="inputStream">${inputStream}</param> -->

</result>

</action>

</package>

 

 

1.4 Struts2OGNL表达式及值栈:

1.4.1 OGNL:

OGNL:表达式语言

* OGNLObject-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。

 

* EL强大很多倍.

* OGNL本身就是一个开源项目,Struts2中引入OGNL作为其表达式.

 

OGNL功能:

   1、支持对象方法调用,如xxx.doSomeSpecial()

   2、支持类静态的方法调用和值访问,表达式的格式:

      @[类全名(包括包路径)]@[方法名 |  值名],例如:

             @java.lang.String@format('foo %s', 'bar')

             或@tutorial.MyConstant@APP_NAME

      设置 struts.ognl.allowStaticMethodAccess=true

   3、访问OGNL上下文(OGNL context)和ActionContext;访问值栈

   4、支持赋值操作和表达式串联,如price=100, discount=0.8,

        calculatePrice(),这个表达式会返回80

   5、操作集合对象。

 

1.4.2 值栈:

以前的操作:Servlet中向jsp传递值!!!

* request/session/application域中存值.JSP页面中从域中取值.

 

Struts2中一般会将这个值保持在一个结构叫做值栈对象中.

* JSP页面中使用OGNL获取值.---Struts2的内部结构中有很多地方依赖了值栈.

 

问题:

什么是值栈?

值栈的内部结构?

值栈ValueStack ActionContext关系? --- 值栈的创建

如何获得值栈对象?

向值栈保存数据?

在页面通过struts2标签 获取值栈内容?

EL为什么能访问值栈中的数据?

 

值栈:ValueStack(值栈): 贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前 Action 对象和其他相关对象.

* Action生命周期:                                     

* Servlet单例的.所有的请求访问LoginServlet,创建一个LoginServlet的对象.(线程安全的问题.)

* Action多例的.每一次访问LoginAction,服务器创建一个LoginAction的对象.(没有线程安全问题.)

* 每一个Action的对象的实例都会有一个ValueStack.

* Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack 的请求属性中,request

* request.setAttribute(struts.valueStack,valueStack);

 

什么是值栈:

ValueStack实际是一个接口,Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack.贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个ValueStack 对象). 相当于一个数据的中转站

值栈内部结构:

值栈中有两块存储空间:

* root:compoundRoot其实就是一个ArrayList.

* context:OgnlContext其实就是一个Map.context中有root的引用,request/session/application/parameters/attr对象引用.

值栈与ActionContext的关系:

每一个Action都有一个属于自己的ValueStack对象.ActionContextAction的上下文.ActionContext中获取到值栈对象.

* 执行doFilter的时候:

* prepare.createActionContext(request, response);---创建ActionContext.

* 跟踪这个方法:

ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();---创建一个值栈对象

ctx = new ActionContext(stack.getContext());---将值栈的对象的上下文传递到ActionContext.

* 所有从ActionContext中获得到ValueStack对象.

 

获得值栈对象:

// 1.通过ActionContext对象获得值栈

ValueStack stack1 = ActionContext.getContext().getValueStack();

// 2.通过request域对象获得值栈.

ValueStack stack2 = (ValueStack) ServletActionContext.getRequest()

.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

System.out.println(stack1 == stack2);

 

如何操作值栈对象:

操作值栈:

* 指的是操作root的那部分!!!

* 操作context需要操作request/session/application对象

 

调用方法操作:

* push(Object obj);

* set(String name,Object obj);

 

***** 但是一般情况下不手动调用pushset也可以!!!

* 因为Action这个类默认就在栈中!!!如果Action有一个属性呢?属性必然会在值栈中.操作的时候只需要在Action中提供一个属性.并且对这个属性提供get方法就可以在页面中获得了.

 

* 如果Action实现了ModelDriven接口的时候,Action默认不在栈顶了,ModelDriven中的对象会在栈顶!!!

页面中获取值栈的数据:

<s:property value=OGNL表达式/>

 

* <s:property value=name>

* <s:property value=[0].top>

 

EL获得值栈的数据:

public class StrutsRequestWrapper extends HttpServletRequestWrapper {

 

    /**

     * The constructor

     * @param req The request

     */

    public StrutsRequestWrapper(HttpServletRequest req) {

        super(req);

    }

 

    /**

     * Gets the object, looking in the value stack if not found

     *

     * @param s The attribute key

     */

    public Object getAttribute(String s) {

        if (s != null && s.startsWith("javax.servlet")) {

            // don't bother with the standard javax.servlet attributes, we can short-circuit this

            // see WW-953 and the forums post linked in that issue for more info

            return super.getAttribute(s);

        }

 

        ActionContext ctx = ActionContext.getContext();

        Object attribute = super.getAttribute(s);

        if (ctx != null) {

            if (attribute == null) {

                boolean alreadyIn = false;

                Boolean b = (Boolean) ctx.get("__requestWrapper.getAttribute");

                if (b != null) {

                    alreadyIn = b.booleanValue();

                }

    

                // note: we don't let # come through or else a request for

                // #attr.foo or #request.foo could cause an endless loop

                if (!alreadyIn && s.indexOf("#") == -1) {

                    try {

                        // If not found, then try the ValueStack

                        ctx.put("__requestWrapper.getAttribute", Boolean.TRUE);

                        ValueStack stack = ctx.getValueStack();

                        if (stack != null) {

                            attribute = stack.findValue(s);

                        }

                    } finally {

                        ctx.put("__requestWrapper.getAttribute", Boolean.FALSE);

                    }

                }

            }

        }

        return attribute;

    }

}

 

***** 增强requestgetAttribute的方法:

* 如果域中有值从域中获取把值返回,如果域中没有这个值,从值栈中找是否有这个值,如果有就返回.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值