欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

shtuts框架精讲

程序员文章站 2022-04-11 18:44:57
...

Struts

请求转发-通过Demo01Action 请求转发到 jump.jsp

Demo01Action

大写的SUCCESS的值为字符串"success" 在底层文件中SUCCESS = "success"
所以 return SUCCESS 相当于 return "success"

package com.lanou3g.jump;

import com.opensymphony.xwork2.ActionSupport;

public class Demo01Action extends ActionSupport{
    @Override
    public String execute() throws Exception {
        System.out.println("Demo01Action");
        return SUCCESS;
    }
}

web.xml

web中需要配置过滤器 在使用action的过程中,无序再为每个类配置servlet,只要配置一个过滤器集合
url-parttern 中写 /* 代表拦截所有的路径 而不是拦截某一个路径 每个action
在经过一个拦截器时,便具备了这个拦截器中的功能

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>sh-struts2-03</display-name>

  <filter>
    <filter-name>struts</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>struts</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

struts.xml

一些xml不支持插入<!DOCTYPE.....>这段内容 显示错误,但是没有关系,即使这一点显示为错误
程序任然可以正常运行 并输出理想的结果 虽然删掉这句错误会消失 但这句话是不可删除的
第一个name可以随便起名 namespace为命名区间,为/时,可以忽略namespace的存在
但如果/后跟的有内容 在通过网址访问时 便需要先写上namespace中的路径 再写
第二个name中的值 extends后的内容为固定的,不可更改 和struts框架底层代码有关联
class后跟的是全限定类名 和具体包中的类产生关联 method是这个类中的方法
该方法为继承父类中的方法 方法名为固定的 用result中的name接收该方法中的返回
值,返回值不一定非要写"success" 只要方法中的返回值和result中的name的值对应上就行

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <package name="test" namespace="/" extends="struts-default" >
        <action name="demo01Action" class="com.lanou3g.jump.Demo01Action" method="execute">
            <result name="success" type="dispatcher" >/jump.jsp</result>
        </action>
    </package>
</struts>

shtuts框架精讲
shtuts框架精讲

小结:请求转发

请求转发 使用dispactcher  使用
<result name="success" type="dispatcher" >/jump.jsp</result>
转发到具体的路径中去 只要路径有效 可以去到任何地方 包括servlet  html action类
写的时候 代码不要写错了!!!!

请求重定向-Demo02Action定向到jump.jsp

在同一个工程下 配置一次过滤器即可 虽然建立了不同的类 但在前一个类已经配置的基础上
web.xml文件已经不需要再添写任何配置了 一次过滤器 可以用到项目结束 相比
servlet,每个类都需要配置一次,功能上提升了很多,减少了代码的书写
在前一个类已经配置了struts.xml的前提下,这次只需要复制粘贴一下package标签中的action即可,然后对里面的
内容稍作小改 使用关键字redirect

struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <package name="test" namespace="/" extends="struts-default" >
        <action name="demo01Action" class="com.lanou3g.jump.Demo01Action" method="execute">
            <result name="success" type="dispatcher" >/jump.jsp</result>
        </action>

        <action name="demo02Action" class="com.lanou3g.jump.Demo02Action" method="execute">
            <result name="success" type="redirect" >/jump.jsp</result>
        </action>
    </package>
</struts>

Demo02Action

package com.lanou3g.jump;

import com.opensymphony.xwork2.ActionSupport;

public class Demo02Action extends ActionSupport{
    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("Demo02Action");
        return "success";
    }
}

shtuts框架精讲

通过Demo03Action 请求重定向 到 Demo01Action

从Demo03Action类重定向到Demo01Action 再从Demo01 请求转发到 jump.jsp

Demo03Action

package com.lanou3g.jump;

import com.opensymphony.xwork2.ActionSupport;

public class Demo03Action extends ActionSupport{
    @Override
    public String execute() throws Exception {
        System.out.println("Demo03Action");
        return "China";
    }
}

struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <package name="test" namespace="/" extends="struts-default" >
        <action name="demo01Action" class="com.lanou3g.jump.Demo01Action" method="execute">
            <result name="success" type="dispatcher" >/jump.jsp</result>
        </action>

        <action name="demo02Action" class="com.lanou3g.jump.Demo02Action" method="execute">
            <result name="success" type="redirect" >/jump.jsp</result>
        </action>

        <action name="demo03Action" class="com.lanou3g.jump.Demo03Action" method="execute">
            <result name="China" type="redirect" >/demo01Action</result>
        </action>
    </package>
</struts>

重定向的另一种方式(常用)

actionName为你要去往的名字
namespace为命名空间 和package里的命名空间(namespace)内容要一致
<action name="demo03Action" class="com.lanou3g.jump.Demo03Action" method="execute">
    <result name="China" type="redirectAction" >
        <param name="actionName">demo01Action</param>
        <param name="namespace">/</param>
    </result>
</action>

shtuts框架精讲
shtuts框架精讲

通过Demo04Action 请求转发到Demo01Action

通过Demo04Action 请求转发到Demo01Action 再由Demo01Action请求转发到jump.jsp

struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <package name="test" namespace="/" extends="struts-default" >
        <action name="demo01Action" class="com.lanou3g.jump.Demo01Action" method="execute">
            <result name="success" type="dispatcher" >/jump.jsp</result>
        </action>

        <action name="demo02Action" class="com.lanou3g.jump.Demo02Action" method="execute">
            <result name="success" type="redirect" >/jump.jsp</result>
        </action>

        <action name="demo03Action" class="com.lanou3g.jump.Demo03Action" method="execute">
            <result name="China" type="redirectAction" >
                <param name="actionName">demo01Action</param>
                <param name="namespace">/</param>
            </result>
        </action>

        <action name="Demo04Action" class="com.lanou3g.jump.Demo04Action" method="execute" >
            <!-- chain Action直接进行转发 -->
            <result name="success" type="chain">
                <param name="actionName">Demo01Action</param>
                <param name="namespace">/</param>
            </result>
        </action>
    </package>
</struts>

Demo04Action

package com.lanou3g.jump;

import com.opensymphony.xwork2.ActionSupport;

public class Demo04Action extends ActionSupport{
    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("Demo04Action");
        return SUCCESS;
    }
}

shtuts框架精讲

获取servletAPI

ActionContext 对象(数据大管家) 内部也是个map集合
ActionContext的生命周期 是跟谁 请求对象(request)走的
如果request对象被销毁 其他对象任然会存在

Servlet 线程不安全(访问共享数据 会发生问题)
整个程序 系统只帮你创建一次 所以多个用户会共用一个servlet
Struts3 线程安全的 如何做到的?
每当有一个用户访问 Struts2就会给你创建一个ActionContext对象

ActionContext对象 可以获取以下对象和域
request对象
response对象
session对象
servletContext对象

requestScope 域 map
sessionScope 域 map
applicationScope 域 map

获取方式一 测试:Demo05Action

Demo05Action中获取域 并给域赋值 然后通过struts.xml中的配置信息 转发到 scope.jsp
在scope.jsp中 将内容输出
package com.lanou3g.servletapi;

import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class Demo05Action extends ActionSupport{
    @Override
    public String execute() throws Exception {
        Map<String, Object> requestScope = (Map<String, Object>) ActionContext.getContext().get("request");
        requestScope.put("name", "我是request");

        Map<String, Object> session = ActionContext.getContext().getSession();
        session.put("name", "我是session");

        Map<String, Object> application = ActionContext.getContext().getApplication();
        application.put("name", "我是application");

        return SUCCESS;
    }
}


<action name="demo05Action" class="com.lanou3g.servletapi.Demo05Action" method="execute">
    <result name="success" type="dispatcher" >/scope.jsp</result>
</action>


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    requestScope: ${requestScope.name } <br/>
    session: ${session.name } <br/>
    application: ${application.name }
         <br/>
</body>
</html>

shtuts框架精讲

获取方式二 测试:Demo06Action

获取原生servlet对象
<action name="demo06Action" class="com.lanou3g.servletapi.Demo06Action" method="execute">
    <result name="success" type="dispatcher" >/scope.jsp</result>
</action>       

<body>
    request: ${request.name } <br/>
    session: ${session.name } <br/>
    application: ${application.name }
         <br/>
</body>

public class Demo06Action extends ActionSupport{
    @Override
    public String execute() throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        request.setAttribute("name", "我是request");

        HttpSession session = request.getSession();
        session.setAttribute("name", "我是session");

        HttpServletResponse response = ServletActionContext.getResponse();

        ServletContext application = ServletActionContext.getServletContext();
        application.setAttribute("name", "我是appilcation");

        return SUCCESS;
    }
}

shtuts框架精讲
shtuts框架精讲

查看jar包的底层文件 可以发现 第二种的实现方式是依赖于第一种实现方式的 第二种实现方式更方便于懂servlet 
jsp的人了解使用 可见虽然底层实现一样 但为了不同的人群 设置了不同的实现方法

获取方式三 测试:Demo07Action

package com.lanou3g.servletapi;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.interceptor.ServletRequestAware;


import com.opensymphony.xwork2.ActionSupport;
/*
 * 通过实现接口的方式
 */
public class Demo07Action extends ActionSupport implements ServletRequestAware{

    private HttpServletRequest request;

    public Demo07Action() {
        System.out.println("Demo07Action 创建了");
    }

    @Override
    public String execute() throws Exception {
        // 直接使用成员变量
        this.request.setAttribute("name", "jiekou");
        return SUCCESS;
    }
    // 接口中的方法
    @Override
    public void setServletRequest(HttpServletRequest request) {
        // TODO Auto-generated method stub
        // 使用成员变量赋值的方式得到servlet对象
        this.request = request;
    }

}


<action name="demo07Action" class="com.lanou3g.servletapi.Demo07Action" method="execute">
    <result name="success" type="dispatcher" >/scope.jsp</result>
</action>   

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    request: ${request.name } <br/>
</body>
</html>
结果截图

shtuts框架精讲
shtuts框架精讲

结果分析
Demo07Action 继承了 ActionSupport类 重写了里面的 execute()方法 同时 Demo07Action
实现了 ServletRequestAware 类 所以又实现了里面的 setServletRequest()方法 这个方法有
个返回值 返回值类型为HttpServletRequest, 所以用HttpServletRequest 类的对象来解释这个返回值

另一个问题就是 execute() 方法 与 setServletRequest() 方法谁先执行 谁后执行的问题
setServletRequest()方法是和过滤器有联系的 在struts-default.xml文档中 第205行 显示为
<interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
打开和它关联的底层文件java代码 发现如下图所示代码 方法intercept的意思为拦截过滤的意思
也就是说当我们提交访问的时候 会先触发过滤器 也就是intercept方法 该方法会在我们的类中
查找有没有ServletRequestAware类以及ServletResponseAware等类的实例化对象 instance of 方法
用来判断该对象是不是属于这个类的 如果是属于其中的那个类 则 根据这个类中的方法 即 setServletRequest(request) 
或者  ((ServletResponseAware) action).setServletResponse(response)等方法 将对象直接返回去 
我们在自己的方法中无需创建对象 只需要接收即可
如果我们需要 HttpServletResponse类的对象 则 实现ServletResponseAware接口即可 底层实现中
也是通过第一种方式的底层实现 获取到 该对象 转了好几个弯 再把对象返回给我们 不过这些弯对我们也可以说是透明的
总的来说 这三种方法的最低层实现是一样的 为了方便我们编写代码 或者 说给我们更多的选择  让我们有多种方式获取对象
另外 根据上述访问三次打印出的结果可以看出 每次访问的时候都新创建了一个对象 所有是线程安全的

shtuts框架精讲
shtuts框架精讲