Struts2学习-2

一、Struts的工作原理及核心过滤器
    1、StrutsPrepareAndExecuteFilter过滤器其实是包含2部分的
            StrutsPrepareFilter:做准备
            StrutsExecuteFilter:进入Struts2的核心处理。如果是Struts2的请求就会进入该过滤器,处理完后,不放行(由结果类负责显示)。如果是非Struts2的请求,比如默认jsp的请求,直接放行。
    如果用不到其他过滤器,配置StrutsPrepareAndExecuteFilter即可;
    如果用到其他过滤器,还需要使用Struts2准备好的环境,使用StrutsPrepareFilter,StrutsExecuteFilter2个过滤器,其他过滤器放在两者之间。如下

showcase,各种应用的案例,在struts2-showcase里面找各种案例
 
2、Struts2中实现了一种可以访问jar包或类路径下的静态资源(css、js等)的方式。
文档中介绍了,可以把静态资源放到org.apache.struts2.static或者template包中,可以直接访问,例如
访问template.aaa中的bbb.css,则
http://localhost:8080/day22_03_strutsStatics/struts/aaa/bbb.css
 
或者自己对静态资源访问的地址进行设置,在web.xml中设置
 <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    <init-param>
        <param-name>packages</param-name>
        <param-value>com.itheima.statics</param-value>
    </init-param>
</filter>
则访问com.itheima.statics中的资源ccc.css,的地址为
http://localhost:8080/day22_03_strutsStatics/struts/ccc.css
 
 
二、在动作类中获取Servlet相关对象的引用
方式一:ServletActionContext的静态方法可以得到Servlet相关的对象
//用Servlet相关的对象request response servletContext HttpSession
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ServletContext sc = ServletActionContext.getServletContext();
HttpSession session = request.getSession();
 
方式二:实现ServletRequestAware接口,struts2框架就会把request对象注入进来,通过拦截器servletConfig。
Action实现如下接口,struts框架则会为其注入相应的Servlet API对象:
ServletRequestAware
ServletResponseAware
ServletContextAware
实现其他对象或者功能,参考拦截器servletConfig。
 
三、自定义拦截器
注意:当拦截器拦截,返回结果集后,则后面的都不会执行,直接返回结果集。
1、执行效率统计拦截器
建立拦截器ElapsedTimeInterceprot实现Interceptor接口
//动作方法及结果处理耗时统计拦截器
public class ElapsedTimeInterceprot implements Interceptor {
    public String intercept(ActionInvocation invocation) throws Exception {
        long beginTime = System.nanoTime();//纳秒:1毫秒=1000000纳秒
        String result = invocation.invoke();//放行:拦截前要做的事放在invocation.invoke()之前,拦截后放在之后
        //结果处理完毕后执行
        long endTime = System.nanoTime();
        System.out.println(invocation.getInvocationContext().getName()+"动作执行耗时:"+(endTime-beginTime)+"纳秒");
        return result;
    }
    public void destroy() {
    }
    public void init() {
    }
}
进行配置文件设置
<package name="p1" extends="struts-default">
    <interceptors>
        <interceptor name="elapsedTime" class="com.itheima.interceptors.ElapsedTimeInterceprot"></interceptor>
    </interceptors>
    <action name="test1" class="com.itheima.action.HelloAction1" method="test1">
        <!-- 需要获取request,所以必须先执行servletConfig拦截器 -->
        <interceptor-ref name="defaultStack"></interceptor-ref>
        <!-- 执行耗时统计拦截器 -->
        <interceptor-ref name="elapsedTime"></interceptor-ref>
        <result>/1.jsp<result>
    </action>
</package>
拦截器的扩展,定义拦截器小组
<package name="p1" extends="struts-default">
    <interceptors>
        <interceptor name="elapsedTime" class="com.itheima.interceptors.ElapsedTimeInterceprot"></interceptor>
        <!-- 自己定义一个拦截器小组 -->
        <interceptor-stack name="myDefaultStack">
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <interceptor-ref name="elapsedTime"></interceptor-ref>
        </interceptor-stack>
    </interceptors>
    <action name="test1" class="com.itheima.action.HelloAction1" method="test1">
        <!-- 执行自定义的拦截器小组 -->
        <interceptor-ref name="myDefaultStack"></interceptor-ref>
        <result>/1.jsp<result>
    </action>
</package>
继续扩展配置设置
<package name="mypackage" extends="struts-default" abstract="true">
    <interceptors>
        <interceptor name="elapsedTime" class="com.itheima.interceptors.ElapsedTimeInterceprot"></interceptor>
        <interceptor name="sessionCheck" class="com.itheima.interceptors.SessionCheckInterceptors">
            <!-- 说明test2动作方法不需要拦截 -->
            <param name="excludeMethods">test2</param>
        </interceptor>
        <interceptor-stack name="myDefaultStack">
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <interceptor-ref name="elapsedTime"></interceptor-ref>
            <interceptor-ref name="sessionCheck"></interceptor-ref>
        </interceptor-stack>
    </interceptors>
    <!-- 设置该包中的所有action配置默认拦截器 ,每个包只能指定一个默认拦截器 -->
    <default-interceptor-ref name="myDefaultStack"></default-interceptor-ref>
</package>
 
2、是否登陆拦截器MethodFilterInterceptor(可以配置是否进行拦截excludeMethods属性,如上)
权限判断拦截器继承MethodFilterInterceptor类,这样只对某些方法起作用,而对其他方法不起作用。 (配置文件如上)
//执行动作方法前检查用户是否已经登录
public class SessionCheckInterceptors extends MethodFilterInterceptor{
    protected String doIntercept(ActionInvocation invocation) throws Exception {
        String result = "login";//对应的就是一个结果
        HttpSession session = ServletActionContext.getRequest().getSession();
        User user = (User)session.getAttribute("user");
        if(user!=null)
            //如果用户有登录,则放行。
            result = invocation.invoke();
        //如果用户没有登录,则返回结果集。
        return result;
    }
}
 配置文件需要在结果集中增加一个
<result name="login">/login.jsp</result>
 
3、注解拦截器
 
*五、ValueStack与s:debug标签
OGNL表达式就是针对一个称之为OGNL根对象和一个称为OGNL Context的Map对象进行操作的语言。
OGNL表达式可以寻址Context内部的对象和直接调用根对象的属性或方法。
ValueStack里面有两个东西,一个是根,就是CompoundRoot,这是一个List集合,还有一个contextMap
获得ValueStack的方式:
ValueStack stack = ActionContext.getContext().getValueStack();
ValueStack被存储在了request作用域中,可以通过request.getAttribute(…)的方式获得。
 
1、OGNL是从一个称之为根栈和contextMap中取数据
        1.1、CompoundRoot就是根的类型。它是List。一般称之为根栈。  取对象的某个属性,OGNL表达式不需要加任何东西,直接写属性即可        
    <!-- 取得valueStack 中name的值,从上往下找-->
    name:<s:property value="name"/><br/>
    <!-- 打印的结果是name这个字符串 -->
    <s:property value="'name'"/>
 
        1.2、OGNL中的contextMap:key和value                    。使用#开头,表示从Context里面取数据。
<s:property value="#session.p"/>
        1.3ActionContext常用的方法(Map)
put()方法和get()方法就是往该Context Map对象中添加数据和取数据。
getApplication()得到application域中的所有attribute的map对象;
getSession()得到代表session域中的所有attribute的map对象;
getParameters()得到代表所有请求参数的map对象;
getLocale()得到当前用户的Locale信息,是综合了session中保存的Locale与浏览器请求消息中的Locale的结果。
     ActionContext ac = ActionContext.getContext();
     Map<String,Object> map = ac.getSession();
     out.write((String)map.get("p"));
     ValueStack vs = ac.getValueStack();
     String s = (String)((Map<String,Object>)vs.getContext().get("session")).get("p");
     ac.put("username""cll");//向contextMap中放数据
     s = (String)ac.get("username");//取数据
 
ServletActionContext类继承了ActionContext类,它额外再提供了一些方便的方法,主要是直接返回Servlet有关的API,
例如,返回HttpServletRequest和HttpServletResponse等,它内部还是调用ActionContext内部保存的那个OGNL Context Map对象。
 
六、ValueStack中常用方法详解
    pop--把栈顶的remove
    push--放到栈顶
(ValueStack)vs.push("abc");结果为
    peek--获取栈顶
    set--往根栈里面放东西,如果栈顶是Map,则直接放进去,如果不是Map,则建一个Map放进去
            set方法不能设置栈顶的普通JavaBean对象的属性。
vs.set("p""pp");//向栈顶压入一个Map(如果栈顶就是一个Map,直接使用了)。map中的元素的key是p,value是pp
    setValue--设置值
  //相当于从栈顶依次查找谁有setItheima("牛13"), 都没有则报错。不会去大Map中找
      vs.setValue("itheima""牛13");
      vs.setValue("date", 18);//某个对象的属性   
  //如果栈顶是一个Map,key就是name,value是furong
  //如果栈顶不是一个Map,修改对象的name属性值为furong 
    Object obj = findValue(String expr):如果expr以#开头,从contextMap中取。如果不加#,先从根栈找属性,没有找到。则从contextMap中,作为key来找了。
    String str = findString:如果找的是Date对象,内部会转换成String对象
    ac.put("now"new Date());
      obj = vs.findValue("#now");
      out.write(obj+" "+obj.getClass().getName());
  //类型转换器把java.util.Date--->java.lang.String.确定表达式返回值就是String类型的才能用
      String str = vs.findString("#now");
取对应的值com.opensymphony.xwork2.ActionContext.locale
obj = vs.findValue("#request['struts.valueStack'].context['com.opensymphony.xwork2.ActionContext.locale']");
 
七、操作ValueStack的通用标签
<s:property>标签用于输出某个OGNL表达式的值,并进行HTML和XML实体转换,可以认为其内部使用的是ValueStack对象的findString()方法。
如果没有设置value属性,则输出ValueStack栈顶的对象,等效于输出“top”这个特殊的OGNL表达式,”top”表示栈顶的对象。
如果采用不加#前缀的方式输出Context中的某个对象,这个对象必须是String类型,以此可以说明该标签内部调用的是ValueStack.findString()方法。
<s:property value="name"/><br/><!-- 相当于ValueStack.findString() -->
<s:property value="top.name"/><br/><!-- top代表栈顶对象,取栈顶对象中的name值  -->
<s:property/><br/><!-- 取栈顶对象 -->
<s:property value="[1].name"/><br/><!-- [1]表示砍掉1个.再取第一个的name属性,后面的不管 -->
<s:property default="木有" value="abc"/><br/><!-- 表示如果没有abc这个属性,则返回default的木有 -->
<s:property value="'<hr/>'" escapeHtml="false"/><!-- escapeHtml默认的是ture,表示打印<hr/> -->
 
<s:push>标签用于将OGNL表达式的值压入栈顶。
<!-- value中的是OGNL表达式 。压倒栈顶后,接着出去了。要想看,把s:debug放在标签中间-->
<s:push value="'abc'"></s:push> 
 
<s:bean>标签用于实例化一个JavaBean对象,并将其压入栈顶。
<s:bean name="java.util.Date" var="date"><!-- Date是一个JavaBean -->
    <s:param name="month" value="11"></s:param><!-- 给对象注入属性值 -->
</s:bean><!-- 需要指定var属性放到contextMap中了 ,不然放到根栈接着出去了-->
 
<s:set>标签用于将某个值存入指定范围域中,通常用于将一个复杂的ognl表达式用一个简单的变量来进行引用。
scope属性:指定变量被放置的范围,该属性可以接受application、session、request、 page或action。该属性的默认值为action
<!-- 注意value里面又是OGNL表达式,需要加引号以示字符串 -->
<s:set name="password" value="'lizongrui'"></s:set>
<!-- 和上面类似,ps为key值,chenguanxi为value -->
<s:set value="'chenguanxi'" var="ps"></s:set>
<!-- scope属性默值为action,表示同时存到了request和OGNL context中。但是dubug标签没显示 -->
<s:set value="'ajiao'" var="pps" scope="action"></s:set>
<!-- 以下验证可以显示出来 -->
<s:property value="#request.pps"/><br/>
 
<s:iterator>使用标签  先引进来struts-tags
<table border="1" bgcolor="blue">
    <tr>
        <th>key</th>
        <th>value</th>
    </tr>
    <s:iterator value="#request" var="me">
        <tr>
        <td><s:property value="#me.key"/></td>
        <td><s:property value="#me.value"/></td>
    </tr>
    </s:iterator>
</table>
以上代码执行的顺序
1。取OGNL Context中的request
2。把第一个key-value的entry,放入到ValueStack中
3。取出放在ValueStack中栈顶的key和value。
4。Value栈顶的Map出栈,再存入request中的第二组entry。。。直到没有数据
 
加var, 表示放到大Map中去了
<table border="1" bgcolor="blue">
    <tr>
        <th>key</th>
        <th>value</th>
    </tr>
    <s:iterator value="#request" var="me" status="s">
        <!-- 使用odd样式或者even样式 -->
        <tr class="<s:property value="#s.odd?'odd':'even'"/>">
        <!-- <tr bgcolor='<s:property value="#s.odd?'#c3f3c3':'#f3c3f3'"/>'> -->
            <td><s:property value="#me.key"/></td>
            <td><s:property value="#me.value"/></td>
        </tr>
        </s:iterator>
</table>
隔行变色。。
s.odd相当于isodd,  is和get一样,.表示取属性值,这里is和get都被省略了
 

猜你喜欢

转载自blog.csdn.net/qq_34801169/article/details/80673066