struts2进阶

1. struts2中获取servletapi, 获取servletactioncontext.getrequest();


2 .采用注入的方式:  java类实现servletrequestaware 接口, 可获取request对象.

    执行流程, 请求被拦截器拦截,有一个默认的servletcofig拦截器,这个拦截器中可以动态的判断action类
       哪个实现了servlet...aware接口, 然后注入给他的setservlet...(传一个对象的引用);



3.OGNL表达式: 三要素,表达式 ,上下文,根

    1.获取上下文对象 new OgnlContext,  2 . 获取根1.getroot(); 3  Ognl.getvalue("对象",1,2);

    4.静态成员访问: 1.getvalue("@java.lang.Math@静态方法或属性",1,2);


4.访问OGNL上下文:

  1 -- 向上下文中存数据 3.1.put("username","tom");
 
  2. Ognl.getvalue("#username",3.1,3.2);  这个地方如果不加#号,就是从根中获取, 你要把map或user对象   
         setroot(map)才能获取,否则就要加#号


  3.操作集合 Ognl.getvalue("{1,2,3,4}",1,2);相当于创建list集合  #{'username':'tom'}创建了map集合

 
   getvalue("username='sfds',age=34")注意这是root,要先setroot(),支持赋值和串联,


5.struts2用OGNL表达式获取valuestack中获取数据,从而达到在页面(jsp)上获取相关的数据.

  要想在jsp使用OGNL表达式, 导入标签库, uri="/struts-tags" prefix="s"

   然后<s:property value="字符串.length()">


6.栈: 先进后出  valueStack 值栈 ,是一个容器,将数据带到jsp页面上.  设计成一个接口了.

   实现类为Ognlvaluestack,

  1.struts2中的action是一个多例的,每一次请求都是一个新的action,所以不存在线程安全问题,

    每一个valuestack对应一个action, 贯穿整个action声明周期. 从request域中获取valuestack.


7.valuestack 内部结构: 有两部分

   1. root 是一个list集合  :  存储action相关数据,

   2. context 是一个map集合  :存储为web开发相关对象. parameters request, session ,aplication,
     里面是map集合等

   3.OGNL如果使用#就从Ognlcontext中获取,没有使用从root中获取.



8.获取valuestack的方式:   他存储在actioncontext中,actioncontext是通过getcontext在线程池里获取的.


   1.request.getattribute(servletactioncontext.str...);

   2.通过actioncontext来获取, actioncontext.getcontext().getvaluestack()

       actioncontext是绑定到线程中, 是每一次请求都会重新创建的

      valuestack中分两部分,他的context部分,每次都会  ctx = new ActionContext(stack.getContext());

       valuestack.getcontext(): 注意在context中持有root的引用.


9.一个request --- action - -- actioncontext---- valuestack(context(root(action)))  stack.push(action);


    ActionContext它是action上下文,strtus2框架它使用actionContext来保存Action在执行过程中所需要的一些对象
      例如 session, application…

      为什么会有这写对象呢?因为它里面有valustack,valuestack中context存储的是对象的map

   ActionContext的获取  是通过它的静态方法getContext()得到。

   Struts2会根据每一次的http请求来创建对应的ActionContext,它是与当前线程绑定的。getcontext方法是从线程池       里面来获取ActionContext对象的

  每一次请求,就是一个线程,对应着一个request,每一次请求,会创建一个Action,每一个action对应一个          ActionContext.每一次请求也对应着一个valueStack.

  request---ActionContext----Action-----ValueStaci它们都对应着一次请求(一个线程).
   valueStack与ActionContext本质上是可以获取



10.valuestack 存储数据

 1.手动存储.向root中存储
     stack.push("Object o"); 向root中存储

     stack.set("",""); 底层会创建一个hashmap,保存数据,把集合存储到root中.


 2.自动向root中存储. 每次请求,都会把action放入到stack.push中;

    a. 会将当前的action对象存储到valuestack中  stack.push(action);在defaultactioninvocation.init方法内
 
    b.如果action实现了modeldriven接口(模型驱动),他会把模型对象存进valuestack中


11. 在jsp页面获取数据

   1. 手动存的数据:

     <s:debug> 可以作为调试用. 取出set里面的数据,set的是map集合直接 <s:property value="map的key">

      而取出push()里面的数据,要清楚他是在栈空间内
      怎么存的,先存的在底部,最底部是一个action, 坐标是从上往下变大的. 要去 某个值 直接[坐标].top

    
  2.自动存的数据:

    他是调用get方法, 直接value="get后面的小写属性";也是存储在root中


  3.实现modeldriven接口的模型类;

    在execute()方法中重新new user();这里不会有模型驱动或者属性驱动,因为这两种驱动只是封装属性的,
    而现在在那个方法内直接用set属性的方式,所以他不会有驱动的事情,只会走个getModel方法.


    而第二个对象取值要jsp页面中value="model.成员属性" 这里model只是在action类中,有一个
    
    getmodel方法内是得到user对象的, 所以用model.成员属性;


  4.EL表达式可以从valuestack中获取数据
   
    struts2对request方法进行增强了.如果在request域中获取不到,就在valuestack中获取

     attribute = stack.findValue(key);


  5.debug中为什么自己设置的user对象是存储在actionstack中的,是因为通过model方法获取的,model方法是在
   action中的.



12. OGNL中 #是从不是root中获取数据 , % 和 $符号; 

  1. #parameters.username 获取地址栏请求参数

  2. %号用法: value=" %{会解析OGNL}"  value="  %{'不会解析'}"

 
  3.$ 号用法:  ${model.username} 可以在值栈中获取值. 注意是:在struts.xml中!!!!  有中文限制



13.在开发中一般继承actionsupprot类, 可以使用父类提供对于错误操作的处理方法,
  addactionError("密码错误"); addfielderror();进行错误信息的校验
  addactionmessage();同时配置了,只会取出最后一个;

  在jsp页面可以使用对应的标签 <s:actionerror/>

  

14.展示商品集合信息:

  1. 在动作类中,可以提供getproduct(),和setproduct()方法,会自动存储到valuestack中

  2. 在动作类中,手动存到值栈中


 在jsp页面中:
 
 1.  <s:iterator value="存的集合名" var="每一个数值">  每一个数值存在context里面,下面要用#    ?

 2.  <s:iterator value="存的集合名" >  直接写属性名;



15.自定义interceptor拦截器

   1. 实现interceptor接口

   2.在配置文件中配置自己的在package标签中<interceptors>
                                            <interceptor name class>
                                              <interceptor-stack name="mystack">
                                                <interceptor -ref name "自己定义的">
                                                <interceptor- ref name="defaultstack">

  3.在action配置中<action><interceptor- ref name="mystack">

  4.注意:当我们显示的引入了一个自定义的Interceptor,那么默认的defaultStack就不会在导入,需要手动         导入。
 

  5.如果登陆放行: return invocation.invoke()

   在拦截器中,获取action invocation.getaction();
   获取到实现actionsupport接口, 然后就可存储错误信息.


  6.使用通配符可以拦截多个方法,但如果只拦截一个方法,自定义需要继承methodfilterinterceptor;

   在配置时<interceptors>
                <interceptor name class> <Param name="includemethods" >放行的方法名
                      <Param name="excludemethods" >不放行的方法

 <default-interceptor-ref name="mystack">




16.存储数据在valuestack中就三个地方:  1.在root中存储  2.在context中存储  3.在action类中的get方法中

  相对应取值的三种方法 root直接取, context加#号取, 类中的加方法名.取值



17. 拦截器拦截请求后,会创建一个action的代理对象,代理会调用execute()方法,会调用invocation的invoke方法,

    在invoke方法内,会遍历所有的拦截器,然后去执行intercept方法,在方法内又会执行invocation.invoke.这样就会

    不断的递归调用拦截器,而请求拦截一遍,响应又拦截一遍.


    例如: params拦截器,当请求参数被拦截器拦截的时候,他就会获得所有的参数,然后,他是被action代理对象调用的

        然后就会知道action对象,然后就会封装了参数.

1.文件上传:    浏览器三要素,  服务器端: commons-fileupload.jar  fileuploadinterceptor拦截器

   1.  继承模型驱动类, 创建 file, contenttype , filename, 成员属性, 在execute方法内将文件copy就可上传.


   2.命名规范:  file 属性命名: jsp页面name,  jsp name+Contenttype ,  jsp name+FileName ; 这里name自定义的


   3.为以上属性提供get,set方法.
    在方法内, io工具类:fileutiles.copyfile(upload,new file(servletcontext.getrealpath(/upload));
 

   4.注意事项: 文件上传有限制大小,在default.properties中,有一个struts.multipart.maxsize=2M;

      1.在struts2  中配置常量,改变值就可以了.这是对整个工程设置


      2. 针对某个action设置 在action下,设置拦截器标签<interceptor-ref name="fileUpload">
          <param name="maximumsize">  <param name="allowedextensions">设置类型, 还要引入默认的拦截器;


      3.上传时如何允许上传多个: 可以在action类中,把三个成员属性设置成集合或数组.在方法内循环数组,完成文件        上传 , 还有就是在jsp中name名称一致;



2. 如果拦截器出现问题,会把错误信息存在action, 然后跳到指定的input视图.可以自定义一个error.jsp,

     然后在struts.xml中配置 result标签的name="input";就会把错误信息显示到.

      将.jsp中两个标签,<s:fielderror> ,<s:actionerror>
       
         <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
          </interceptor-ref>

 

3. json数据格式: 对象和数组可以互相嵌套.

 * 1.fastjson json工具在json和java之间转换,  JSONobjct.toJSONString(对象); JSONArray.toJSONString(集合);

       1. 以上解决日期格式: 注解@JSONField(format="yyyy-mm-dd");  阿里独有的注解

       2. 处理不想要的属性JSONobjct.toJSONString(对象,new propertyfilter(

           重写 apply(要转换成json的对象,属性名称,属性值){
                        if属性名称.equal() return false;
              }));



  2. 另一种jackson 工具类, 导入jar包,new ObjectMapper.writevalueasstring(对象或数组);重载的方法特别多

      mapper.writeValue(ServletActionContext.getResponse().getWriter(), 对象或数组);

     1. 解决日期: mapper.setDateFormat(new Simpledatformat());设置日期格式器;

     2. 过滤属性: 注解@JsonIgnoreproperties({"属性1","属性2"})在类上面;这是使用这个类的全部过滤

         处理一个类的过滤属性 mapper.setfilter(new simplefilterprovider.addfilter(

           注解的自定名 ,simplebeanpropertyfilter.serializeallexcept(不想要的属性1,...)));

           在类上加注解@JsonFilter("自定义名")



4.当出现死循环转换时候, 例如订单关联客户,客户关联订单, 当转客户为json格式时候,

  1.除了fastjson,都会内存溢出;

      如果关闭fastJson,JSON.toJSONString(customer,SerializerFeature.DisableCircularReferenceDetect)  
 
       不想用哪个属性, @JSONField(serialize=false) 在这个属性上面private Customer c;


  2.其他工具内存溢出解决,直接不要那个属性了,加注解@JsonIgnore
5.struts.xml分文件, <include file="..xml"/>



6.struts2处理ajax请求.创建一个result类, 两个属性: 描述是否可用,错误信息; 把result类转换为json

  mapper.writervalue( response.getwriter,result);注意解决乱码;

  js代码中eval("("+data+")")将data转为js对象;括号一定要加;



7. struts2框架的json插件. 导入jar包,将struts.xml <package extends="json-defalut">

     action的返回视图<result type="json"> , struts2框架就会将valuestack的"栈顶"元素转为json格式.

     响应到浏览器,所以不用response转为json了,只需要把集合或对象压入栈顶就可以了.



8.关于响应json的处理,  忽略属性 : 在jsonresult类中有两个属性; includeproperties包含 不包含exclude....

  在struts.xml中 的result标签下,设置root,<param name="root">ps  这样会把ps后面的[]取出来;
  <param name="excludeproperties">\[\d+\]\.属性名    要把[] 转义 所以 \[\]

  javascript:void(0);  相当于#;



9.注解开发;

    导入convention-plugin-2.3.24.jar包, 2.1版本以后才能
    1.在类上面@Namespace("/")  相当于namspace="/"  @parentPackage("struts-defult")

    2.在方法上面@action(value="hello",results={@result(name="" ,type="",location=".jsp")})

10.在类上面:actions: 可以用过多个映射来访问同一个action.  results : 全局返回视图  

     他默认只会扫描包名为action,actions,sturts,staurts2. 类名: Action结尾:

      如果别的名字,就需要在xml中配置常量 name="struts.convention.package.locators"  action.suffix类名

猜你喜欢

转载自blog.csdn.net/xc123_java/article/details/74091836