请求处理

2020-12-07  本文已影响0人  _FireFly_

请求-响应过程中struts功能详解

1. 接收请求

2. 映射请求

有3种请求映射方式:

第1种:一个<action>配置对应一个请求
        <action name="test1" class="com.action.TestAction" method="t1"></action>
        <action name="test2" class="com.action.TestAction" method="t2"></action>
第2种:动态方法调用,一个<action>配置对应多个请求
  1. 浏览器发请求时要符合以下规则
    /test!t3.do
    /test!t4.do
    • 上述2个请求语法都表示发送test.do请求
    • 后面的t3和t4表示处理请求的方法名
  2. 在struts.xml配置文件中重置属性,开启动态方法调用
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
  3. 配置<action>
    <action name="test" class="com.action.TestAction"></action>
  4. 在struts.xml的<package>中,指定允许动态方法调用的方法名。
    <global-allowed-methods>t3,t4</global-allowed-methods>
第3种: 通配符匹配,一个<action>配置对应多个请求
  1. 浏览器发送请求时要符合一定的规则(自定义)
    /Test_t5.do
    /Test_t6.do
  2. 使用通配符配置<action>
    <action name="Test_
    " class="com.action.TestAction" method="{1}"></action>
    {1} 代表第1个*代表的位置
<action name="Test_*_*" class="com.action.{1}Action" method="{2}"></action>
等价于
<action name="Test_*_*" class="com.action.UserAction" method="t5"></action>
  1. 在struts.xml的<package>中,指定允许动态方法调用的方法名。
    <global-allowed-methods>t3,t4</global-allowed-methods>

3. 请求处理

 <param name="size" >10</param>

<input name="user.uname" />
public class User implements Serializable {
    private Integer uno ;
    private String uname ;
    private String upass ;
    private Integer age ;

    public Integer getUno() {
        return uno;
    }

    public void setUno(Integer uno) {
        this.uno = uno;
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public String getUpass() {
        return upass;
    }

    public void setUpass(String upass) {
        this.upass = upass;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public User(Integer uno, String uname, String upass, Integer age) {
        this.uno = uno;
        this.uname = uname;
        this.upass = upass;
        this.age = age;
    }

    public User() {
    }
}
public class TestAction2 {

    private String uname ;
    private int age ;
    public void setUname(String uname) {
        this.uname = uname;
    }
    public void setAge(int age) {
        this.age = age;
    }

    public void t2(){
        //String uname = request.getParameter("uname");
        System.out.println(uname+"--------------"+age);
    }
}

扩展:值栈

image.png

在每次请求时,struts会根据请求映射的配置,创建action对象并调用方法

  1. 于此同时还会创建一个值栈对象
  2. 值栈用来存放请求响应过程中的一些数据内容,如:request,response,session,application等
  3. 值栈栈顶装载的就是action对象
  4. struts有一个params拦截器,负责接收参数
  5. 接收参数后,会获得值栈栈顶的对象(默认是action), 为其(根据set方法)传递参数
  6. 如果发现action实现了ModelDriven接口
  7. modelDriven拦截器会通过getModel()获得对象(user),将对象装入栈顶
  8. params再赋值时,就是为user对象赋值(通过set方法),获取servlet相关对象 request , response , session , application等
* 方式1:通过ActionContext获得一个具有session存储功能的Map对象

Map<String,Object> session = ActionContext.getContext().getSession();
session.put("uname",uname) ;//相当于session.setAttribute("uname",uname);

public class TestAction1 {

    private String uname ;
    public void setUname(String uname) {
        this.uname = uname;
    }

    public void t1(){
        System.out.println("----------------" + uname);
        //将unmae参数值装入session对象
        Map<String,Object> session = ActionContext.getContext().getSession();
        session.put("uname",uname) ;//相当于session.setAttribute("uname",uname);

        //ActionContext.getContext().put("k","v");//相当于request.setAttribute(k,v);
        //ActionContext.getContext().getApplication().put("k","v");//相当于application.setAttribute(k,v)
    }
}
* 方式2: 通过SerlvetActionCotnext获得原生servlet相关对象

HttpServletRequesst,HttpServletResponse,HttpSession

ServletActionContext.getRequest();
request.getSession(); //sessioin
request.getServletContext(); //application
ServletActionContext.getResponse();

public class TestAction2 {

    private int age ;
    public void setAge(int age) {
        this.age = age;
    }

    public void t2(){
        System.out.println("==============" + age );
        //将action装入session
        ServletActionContext.getRequest().getSession().setAttribute("age",age); ;
    }

}
* 方式3:通过实现接口,配合拦截器,使用DI方式获得原生servlet相关对象
  1. action实现SessionAware接口,重写方法
  2. action中定义session属性
  3. set方法中赋值
    private Map<String,Object> session ;
    public void setSessioin(Map<String,Object> map){
    this.session = map ;
    }
public class TestAction3 implements SessionAware {

    private String sex ;
    public void setSex(String sex) {
        this.sex = sex;
    }
    private Map<String,Object> session ;

    public void t3(){
        System.out.println("++++++++++++++++++++" + sex);
        //将sex装入session
    }

    @Override
    public void setSession(Map<String, Object> map) {
        this.session = map ;
    }
}
实现机制:

在struts的请求处理过程中,先通过拦截器(servletConfig)对action进行检测,如果发现该action实现了接口SessionAware,struts就会根据set方法传入session对象(DI 依赖注入)

补充:

action实现了ServletRequestAware接口 获得HttpServletRequest
action实现了ServletResponseAware 接口 获得HttpServletResponse
* 扩展:
通过上述3种方式的源码分析发现获取的所有对象最终都来自ActionContext
所以没有性能差别

上一篇 下一篇

猜你喜欢

热点阅读