美文网首页
请求处理

请求处理

作者: _FireFly_ | 来源:发表于2020-12-07 09:33 被阅读0次

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

1. 接收请求

  • 浏览器向服务器发送请求
  • 服务器根据web.xml(核心过滤器)的配置将请求交给struts框架
  • 但struts框架不一定所有的请求都处理。
  • 默认:只接收处理 .action后缀的请求或没有后缀的请求
    /test.action
    /test
  • 可以重置struts.action.extension 属性改变处理请求的后缀

2. 映射请求

  • struts根据<action>配置,找到与此次请求对应的处理类

    <action name="test" class="com.action.TestAction" method="t1"></action>

    • 注意:映射请求时,不再携带后缀匹配
      • 发送的请求是test.do
      • 映射的请求是test
      • .do后缀在接收请求时起作用
    • 注意:处理请求的action类就是一个普通pojo类,不需要任何继承(对比 servlet)
    • 注意:<action method="">没有配置则默认调用execute方法,配置则调用指定方法。
    • 注意:处理的请求方法不能有任何参数
      如果有响应处理,设置String返回值,否则void。

有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个*代表的位置
  • 扩展:
    /Test_User_t5.do
    /Test_Book_t6.do
    在struts.xml配置文件中
<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. 请求处理

  • 接收参数:
  • 接收action对象的初始化参数
  • 我们定义的action类,但由struts框架负责管理(创建,调用) (IOC 控制反转)
  • 在struts.xml中,使用<action>的子标签<param> 指定初始化参数
 <param name="size" >10</param>
  • 在action类中定义与上述参数同名的属性,并实现set方法
  • 属性类型与参数值匹配即可。
  • 注意:struts在创建action时会自动调用set方法为action传递初始化参数 (DI 依赖注入)
  • 接收请求传递的独立参数
  • 在action中定义与请求参数同名的属性,并实现set方法
  • 属性类型与参数值匹配即可。
  • 接收传递的对象参数
  • 传递了多个参数,且这些参数恰好可以组成一个对象。
  • 在浏览器(网页)请求传参时,需要为每一个参数提供一个统一对象名前缀,如:
    /test3.do?user.uname=dmc&user.upass=123&user.age=18&user.uno=1001

<input name="user.uname" />
  • 定义装载参数的类(User)
  • 隐藏条件:类属性名必须与请求的参数名一致
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() {
    }
}
  • 在action中定义User类型的属性,属性名就是参数的前缀名,并实现set/get方法
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);
    }
}
  • 扩展: 接收请求传递的对象参数 (模型驱动)
  • 浏览器(网页) 正常传参, 参数不需要提供对象名前缀
    /test4.do?uname=dmc&upass=123&age=18&uno=1001
  • action类 实现 ModelDriven<User>接口,设置User泛型 , 重写方法(getModel)
  • action类中定义User类型属性,并创建对象。
    User user = new User();
  • 在getModel()方法中,返回一个user属性值
    public User getModel() {
    return user;
    }
  • 机制:
    • struts框架创建action时
    • 会通过检测机制(拦截器)发现action实现了ModelDriven接口
    • 就会调用action的getModel方法获得一个返回的(user)对象
    • 将获取的参数装载到(值栈顶)user对象中。

扩展:值栈

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);

  • 扩展:
    ActionContext.getContext().put("k","v");//相当于request.setAttribute(k,v);
    ActionContext.getContext().getApplication().put("k","v");//相当于application.setAttribute(k,v);
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
所以没有性能差别

相关文章

网友评论

      本文标题:请求处理

      本文链接:https://www.haomeiwen.com/subject/ukubwktx.html