Struts2拦截器和数据封装

目录

1、   在Struts2框架中使用Servlet的API

2、   页面跳转

3、   Struts2框架的数据封装

4、   拦截器部分

内容

1、在Struts框架中使用servlet的API

1.1 在Action类中也可以获取到Servlet一些常用的API

       *需求:提供JSP的表单页面的数据,在Action中使用Servlet的API接收到,然后保存到三个域对象中,最后再显示到JSP的页面上。

           *提供JSP注册的页面,演示下面这三种方式

              <h3>注册页面</h3>

              <formaction="${ pageContext.request.contextPath }/xxx.action"method="post">

                  姓名:<inputtype="text" name="username" /><br/>

                  密码:<inputtype="password" name="password" /><br/>

                  <inputtype="submit" value="注册" />

              </form>

    1.2. 完全解耦合的方式

       *如果使用该种方式,Struts2框架中提供了一个类,ActionContext类,该类中提供一些方法,通过方法获取Servlet的API

       *一些常用的方法如下

           *static ActionContext getContext()                                   -- 获取ActionContext对象实例

           *返回值java.util.Map<java.lang.String,java.lang.Object>getParameters()          -- 获取请求参数,相当于request.getParameterMap();

           *java.util.Map<java.lang.String,java.lang.Object> getSession()           --获取的代表session域的Map集合,就相当于操作session域。

           *java.util.Map<java.lang.String,java.lang.Object> getApplication()       -- 获取代表application域的Map集合

           *void put(java.lang.String key, java.lang.Object value)                  --注意:向request域中存入值。

    1.3. 使用原生Servlet的API的方式

       *Struts2框架提供了一个类,ServletActionContext,该类中提供了一些静态的方法

       *具体的方法如下

           *getPageContext()

           *getRequest()

           *getResponse()

           *getServletContext()


2、页面跳转

2.1. 结果页面存在两种方式

       *全局结果页面

           >条件:如果<package>包中的一些action都返回success,并且返回的页面都是同一个JSP页面,这样就可以配置全局的结果页面。

           >全局结果页面针对的当前的包中的所有的Action,但是如果局部还有结果页面,会优先局部的。使用的标签是

              <global-results>

                  <result>/demo3/suc.jsp</result>

              </global-results>

       *局部结果页面

           <resultname=””>/demo3/suc.jsp</result>

   2.2. 结果页面的类型

       *结果页面使用<result>标签进行配置,包含两个属性

           >name -- 逻辑视图的名称

           >type -- 跳转的类型,值一些,需要掌握一些常用的类型。常见的结果类型去struts-default.xml中查找。

              *dispatcher      -- 转发.type的默认值.Action--->JSP

              *redirect        -- 重定向. Action--->JSP

              *chain             -- 多个action之间跳转.从一个Action转发到另一个Action.    Action---Action

              *redirectAction  -- 多个action之间跳转.从一个Action重定向到另一个Action.    Action---Action

              *stream          -- 文件下载时候使用的

3、Struts2框架的数据封装

3.1 第一种方式:属性驱动

           >提供对应属性的set方法进行数据的封装。

              *表单的哪些属性需要封装数据,那么在对应的Action类中提供该属性的set方法即可。

              *表单中的数据提交,最终找到Action类中的setXxx的方法,最后赋值给全局变量。

              *注意0:Struts2的框架采用的拦截器完成数据的封装。

              *注意1:这种方式不是特别好:因为属性特别多,提供特别多的set方法,而且还需要手动将数据存入到对象中.

              *注意2:这种情况下,Action类就相当于一个JavaBean,就没有体现出MVC的思想,Action类又封装数据,又接收请求处理,耦合性较高。

          

           >在页面上,使用OGNL表达式进行数据封装。这里OGNL和jstl有一些类似,只是OGNL在jsp页面的存取都需要去使用下面这种方式

              *在页面中使用OGNL表达式进行数据的封装,就可以直接把属性封装到某一个JavaBean的对象中。

              *在页面中定义一个JavaBean,并且提供set方法:例如:private User user;这里是在domain下创建JavaBean,然后在action类下创建user的set方法。

              *页面中的编写发生了变化,需要使用OGNL的方式,表单中的写法:<input type="text"name="user.username">

              *注意:只提供一个set方法还不够,必须还需要提供user属性的get和set方法!!!

                  >先调用get方法,判断一下是否有user对象的实例对象,如果没有,调用set方法把拦截器创建的对象注入进来,

      

3.2 第二种方式:模型驱动

           >使用模型驱动的方式,也可以把表单中的数据直接封装到一个JavaBean的对象中,并且表单的写法和之前的写法没有区别!

           >编写的页面不需要任何变化,正常编写name属性的值

           >模型驱动的编写步骤:

              *手动实例化JavaBean,在Action类中:privateUser user = new User();

              *Action类必须实现ModelDriven<T>接口,实现getModel()的方法,在getModel()方法中返回user即可!!同时还需要继承ActionSupport类模块开发

3.3 Struts2把数据封装到集合中(了解)

3.3.1. 封装复杂类型的参数(集合类型 Collection 、Map接口等)

3.3.2. 需求:页面中有可能想批量添加一些数据,那么现在就可以使用上述的技术了。把数据封装到集合中

    3.3.3.把数据封装到Collection中

       *因为Collection接口都会有下标值,所有页面的写法会有一些区别,注意:

            <input type="text"name="products[0].name" />

       *在Action中的写法,需要提供products的集合,并且提供get和set方法。

       privateList<Product> list;

    3.3.4.把数据封装到Map中

       *Map集合是键值对的形式,页面的写法

           ><input type="text" name="map['one'].name" />

       *Action中提供map集合,并且提供get和set方法

       *private Map<String,User> map;


4、Struts2框架拦截器

4.1拦截器技术

4.1.1. 拦截器的概述

       *拦截器就是AOP(Aspect-Oriented Programming)的一种实现。(AOP是指用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。)


       *过滤器:过滤从客服端发送到服务器端请求的

       *拦截器:拦截对目标Action中的某些方法进行拦截

           *拦截器不能拦截JSP

           *拦截到Action中某些方法

       切面编程和纵向编程(父类)的区别见图


4.1.2. 拦截器和过滤器的区别

       1)拦截器是基于JAVA反射机制的,而过滤器是基于函数回调的

       2)过滤器依赖于Servlet容器Tomcat服务器,而拦截器不依赖于Servlet容器

       3)拦截器只能对Action请求起作用(Action中的方法),而过滤器可以对几乎所有的请求起作用(CSS JSP JS)

       *拦截器 采用 责任链模式

           >在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链

           >责任链每一个节点,都可以继续调用下一个节点,也可以阻止流程继续执行

       *在struts2 中可以定义很多个拦截器,将多个拦截器按照特定顺序 组成拦截器栈 (顺序调用 栈中的每一个拦截器 )

4.1.3. Struts2的核心是拦截器, Struts2的运行流程


2、服务器启动时候就已经执行Configuration Manager了

1、ActionMapper首先解析路径的请求/user_save.action

3、ActionProxy生成一个访问的Action的代理对象

4、ActionInvocation对象 管理所有的拦截器。采用递归的方式进行一个一个拦截器的调用。

5、拦截器按顺序执行,执行完成后再让真正的Action执行

6、执行Result。找一个Template(末班)进行渲染

2、自定义拦截器和配置

2.1. 编写拦截器,需要实现Interceptor接口,实现接口中的三个方法

  protectedString doIntercept(ActionInvocation invocation) throws Exception {

           //获取session对象

           Useruser = (User)ServletActionContext.getRequest().getSession().getAttribute("existUser");

           if(user== null){

              //说明,没有登录,后面就不会执行了

              return"login";

           }

           returninvocation.invoke();

       }

    2.需要在struts.xml中进行拦截器的配置,配置一共有两种方式

 <!--定义了拦截器 第一种方式  在包里配置

       <interceptors>

           <interceptorname="DemoInterceptor"class="com.itheima.interceptor.DemoInterceptor"/>

       </interceptors>

       -->

       <actionname="userAction" class="com.itheima.demo3.UserAction">

           <!--只要是引用自己的拦截器,默认栈的拦截器就不执行了,必须要手动引入默认栈

           <interceptor-refname="DemoInterceptor"/>

           <interceptor-refname="defaultStack"/>   

       </action>

       <!--第二种方式:定义拦截器栈 -->

       <interceptors>

           <interceptorname="DemoInterceptor"class="com.itheima.interceptor.DemoInterceptor"/>

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

           <interceptor-stackname="myStack">

              <interceptor-refname="DemoInterceptor"/>

              <interceptor-refname="defaultStack"/>

           </interceptor-stack>

       </interceptors>

      <action name="userAction"class="com.itheima.demo3.UserAction">

           <!--引入拦截器栈就OK -->

           <interceptor-refname="myStack"/>

       </action>

案例2 使用拦截器判断用户是否已经登录

使用过滤器也可以做

1、创建自定义拦截器,判断当前系统是否已经登录,如果登录,继续执行。如果没有登录,跳转到登录页

 publicclass UserInterceptor extends MethodFilterInterceptor{

    //其中继承MethodFilterInterceptor能够将login放行

    privatestatic final long serialVersionUID = 335018670739692955L;

   

    /**

     * 进行拦截的方法

     *实现继承的方法

     */

    protectedString doIntercept(ActionInvocation invocation) throws Exception {

       //获取session对象

       Useruser = (User)ServletActionContext.getRequest().getSession().getAttribute("existUser");

       if(user== null){

           //说明,没有登录,后面就不会执行了

           return"login";

       }

       returninvocation.invoke();

      }

   }

在配置一下全局的<globle-result>、配置自定义的拦截器以及user和Customer的action标签中的拦截器和默认拦截器的引用

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

       <!--配置拦截器 -->

       <interceptors>

           <interceptorname="UserInterceptor"class="com.itheima.interceptor.UserInterceptor"/>

       </interceptors>

       <global-results>

           <resultname="login">/login.htm</result>

       </global-results>

       <!--配置用户的模块 -->

       <actionname="user_*" class="com.itheima.action.UserAction"method="{1}">

           <!--<result name="login">/login.htm</result> -->

           <resultname="success">/index.htm</result>

           <interceptor-refname="UserInterceptor">

              <!--login方法不拦截 -->

              <paramname="excludeMethods">login</param>

           </interceptor-ref>

           <interceptor-refname="defaultStack"/>

       </action>

       <!--客户模块 -->

       <actionname="customer_*" class="com.itheima.action.CustomerAction"method="{1}">

           <interceptor-refname="UserInterceptor"/>

           <interceptor-refname="defaultStack"/>

       </action>

      

    </package>

其中在<paramname="excludeMethods">login</param>中的login表示的是自己写的登录方法

    publicclass UserAction extends ActionSupport{

    privatestatic final long serialVersionUID = 1305643617977647333L;

    /**

     * 处理登录功能

     * @return

     */

    publicString login(){

       //这边没有学习功能,封装数据,现在还需要使用request对象

       //怎么获取request方式

       HttpServletRequestrequest = ServletActionContext.getRequest();

       //获取请求参数

       Map<String,String[]> map = request.getParameterMap();

       Useruser = new User();

       try{

           BeanUtils.populate(user,map);

           //调用业务层

           UserexistUser = new UserService().login(user);

           //判断

           if(existUser== null){

              //说明,用户名或者密码错误了

              returnLOGIN;

           }else{

              //存入到session中

              request.getSession().setAttribute("existUser",existUser);

              returnSUCCESS;

           }

       }catch (Exception e) {

           e.printStackTrace();

       }

        return NONE;

    }

}

前端页面需要配置一下login.htm请求的tagart的属性

    <FORMid=form1 name=form1 action="/day32_crm/user_login.action" method=posttarget="_parent">

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值