zoukankan      html  css  js  c++  java
  • (二)、Struts第二天

    ()Struts第二天

    回顾:

    问题:

    1. Struts2Action类是单例还是多例? Filter? Servlet? Listener?

    2. 介绍struts2框架引入的相关jar包及作用?

    3. Struts2 配置文件中,名称空间作用?

    4. Struts2 执行流程

     

    目标:

    0. Action类的几种写法

    1. Struts核心配置

    常量配置

    通配符/动态方法调用

    全局视图、全局异常、Action配置各项的默认值

    2. 拦截器

     

    1. Action类的几种写法

    1。 搭建struts开发环境

    2.  Action类、配置Action

     

     

    开发Action:

    1. 写一个普通的java类;

    2. 写一个普通的java实现Action接口 【可以使用常量】

    3. 写一个普通的java类;继承ActionSupport类    【常用; 】

             如果使用struts提供的数据效验功能,必须继承ActionSupport!

     

    public class DemoAction {}

    public class DemoAction implements  Action {}

    public class DemoAction extends ActionSupport {}

    2. 通配符

    语法如: user_*      * 的值由访问时候传入的值确定;

    引用的时候,用{1}引用*的值

     

    传统的写法,

     

    <!-- 访问:  http://localhost:day28/save.action

    方式1:传统的写法

    <action name="save" class="cn.itcast.a_action.DemoAction" method="save">

    <result name="save">/a/save.jsp</result>

    </action>

    <action name="delete" class="cn.itcast.a_action.DemoAction" method="delete">

    <result name="delete">/a/delete.jsp</result>

    </action>

    <action name="update" class="cn.itcast.a_action.DemoAction" method="update">

    <result name="update">/a/update.jsp</result>

    </action>

     -->

     

     

    使用通配符优化配置

    <!-- 

    方式2:使用通配符优化配置

    访问:  http://localhost:day28/demo_save.action

    访问:  http://localhost:day28/demo_update.action

     -->

    <action name="demo_*" class="cn.itcast.a_action.DemoAction" method="{1}">

    <result name="{1}">/a/{1}.jsp</result>

    </action>

     

    特殊的用法,

    <!-- 

    注意:

    访问1: http://localhost:8080/day28/demo_execute

         如果方法返回的是success,可以省略名称

          <result name=success>/index.jsp</result>  

          <result>/index.jsp</result>        同上

    方式2http://localhost:8080/day28/demo

    要求: 

    1. 必须有execute方法默认找execute方法

    2. execute方法,必须返回success;

     -->

    <action name="demo_*" class="cn.itcast.a_action.DemoAction" method="{1}">

    <result>/index.jsp</result>

    </action>

     

     

    3. 动态方法调用(了解)

    <!-- 

      另外的方式:

      动态方法调用:

      语法: !  感叹号后面的就是要处理的Action类中的方法名称!

      举例: 

      http://localhost:8080/day28/demo!save

      表示actionName demo对应的Action类,必须有一个save方法!

        

                动态方法调用与通配符区别?

          1. 配置

           通配符是用与 {1}  配合使用

           动态方法调用是在访问的时候通过!符合指定方法名称

          2. 比较

           建议使用通配符! 不要用动态方法调用! (相对不安全!)

           开发中都会禁用这个功能!

      -->

     <action name="demo" class="cn.itcast.a_action.DemoAction">

    <result>/index.jsp</result>

    <result name="save">/a/save.jsp</result>

    <result name="update">/a/update.jsp</result>

    <result name="delete">/a/delete.jsp</result>

    </action>

     

    4. 全局相关配置

     

    全局视图、全局异常、配置各项默认值!

    <?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="user_new" extends="struts-default">

    <!-- 4. 默认执行的action类 -->

    <!-- 测试:指定默认执行的action类! 会覆盖调struts-default.xml中默认执行的Action(ActionSupport) -->

    <default-class-ref class="cn.itcast.b_config.DefaultAction"></default-class-ref>

    <!-- 

    1. 全局跳转视图配置

    这里面的配置,可以供当前包下所有的action共享!

     -->

     <global-results>

      <result name="success">/index.jsp</result>

      <result name="error">/error.jsp</result>

     </global-results>

     

     <!-- 

      2. 全局异常配置

      当此包下的action类执行出现空指针异常,会取找error对应的全局视图对应的页面进行跳转!

      -->

     <global-exception-mappings>

      <exception-mapping result="error" exception="java.lang.NullPointerException"></exception-mapping>

     </global-exception-mappings>

     

    <action name="user_*" class="cn.itcast.b_config.UserAction" method="{1}">

    </action>

     

    <action name="order_*" class="cn.itcast.b_config.OrderAction" method="{1}">

    </action>

    <!-- 

    3. 各项目配置默认值

    name  访问路径资源

    class 默认执行的Action类是:ActionSupport!

       在struts-default.xml配置文件中配置,

    <default-class-ref class="com.opensymphony.xwork2.ActionSupport" /> 

     表示默认执行的action类! 用户开发时候,可以在自己的package中进行配置,那么会覆盖父类的配置!

     

      method 默认执行execute方法

                           且返回success, 但当前没有配置对应页面,所以会取找全局视图配置!

    --> 

    <action name="test"></action>

    <!-- 作用:可以跳转到WEB-INF下资源,但不用写Action类!

    <action name="test">

    <result name="success">/WEB-INF/index.jsp</result>

    </action>

     -->

     

    </package>

     

    </struts>

     

     

     

    5. 常量配置

    思考:struts2访问后缀能否修改?

    -à 先找到定义的位置

    -à 定义自己设置的后缀,覆盖默认

     

     

    常量定义位置:

    struts2-core-2.3.4.1.jar/org.apache.struts2/default.properties

    struts.xml中定义常量:

    <constant name=" " value=" "/>

     

     

        指定默认编码集,作用于HttpServletRequestsetCharacterEncoding方法 和freemarker velocity的输出 

        <constant name="struts.i18n.encoding" value="UTF-8"/>

        自定义后缀修改常量 

        <constant name="struts.action.extension" value="do"/>

        设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 

        <constant name="struts.serve.static.browserCache" value="false"/>

        struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 

        <constant name="struts.configuration.xml.reload" value="true"/>

        开发模式下使用,这样可以打印出更详细的错误信息 

        <constant name="struts.devMode" value="true" />

        默认的视图主题 

        <constant name="struts.ui.theme" value="simple" />

        spring集成时,指定由spring负责action对象的创建 

        <constant name="struts.objectFactory" value="spring" />

        该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性

        为 false

        <constant name="struts.enable.DynamicMethodInvocation" value="false"/>

        上传文件的大小限制 

        <constant name="struts.multipart.maxSize" value=“10701096"/>

     

     

     

    6. 数据处理

    方式1ActionContext 获取表示域对象的map

    这样就可以通过操作map来操作域对象!

    方式2: 实现接口的方式, 获取表示域对象的map集合!

    RequestAware/SessionAware/ApplicationAware

    原理:servletConfig拦截器!注入的map是从ActionContext对象获取的map!

    方式3ServletActionContext 获取原始的ServletApi

     

     

    (一) 方式2实现:

     

    /**

     * 所有的action可以继承此类,就可以直接用map集合  保存数据!

     * @author AdminTH

     *

     */

    public class BaseAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware {

    protected Map<String, Object> request;

    protected Map<String, Object> session;

    protected Map<String, Object> application;

    // 在运行时期(servletConfig拦截器), struts会把表示requestmap注入进来!

    @Override

    public void setRequest(Map<String, Object> request) {

    this.request = request;

    }

    // 在运行时期(servletConfig拦截器), struts会把表示sessionmap注入进来!

    @Override

    public void setSession(Map<String, Object> session) {

    this.session = session;

    }

    // 在运行时期(servletConfig拦截器), struts会把表示applicationmap注入进来!

    @Override

    public void setApplication(Map<String, Object> application) {

    this.application = application;

    }

    }

     

     

    (二) 方式2实现原理:

     

    Struts-defualt.xml 中关于servletConfig拦截器!

     

     

     

     

     

    7. 用户库

    MyEclipse如何管理jar文件?

    答案:用户库!

     

    使用步骤:

    1. 新建用户库

    --à选中项目,右键,properties

    -àLibrary,   右侧Add Library

    -à ……

     

    2. 发布项目

    检查tomcat下是否有用户库的jar包!

    如果有,直接启动!

     

     

    注意:

    如果用户库中的jar包没有发布到tomcat下,按照

    《构建用户库-步骤图解.doc》 操作!

     

     

    8. 共性问题

    问题1: Struts.xml没有提示?

     

    解决a: 配置MyEclipse关联约束!

    <!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

    "http://struts.apache.org/dtds/struts-2.3.dtd">

     

    步骤:

    1. 源码找到文件: struts-2.3.dtd存到到指定目录(E:DTD

    2. Windows-à Preferences -à XML Catalog

    Location: 定位到dtd文件的目录路径(如:E:DTD)

    Key:  -//Apache Software Foundation//DTD Struts Configuration 2.3//EN

    3. OK; 关闭XML; 重新打开! 

     

    解决b: 连接internet即可! 工具会自动下载!

    或者,

    手写!

     

     

     

     

    问题2: @Override 报错?

     

    解决1. 

    @Override  删除即可!

    解决2. 或者,

    修改编译环境为1.6以上的环境!

     

    JDK1.5 只支持对父类方法的@Override不支持接口的@Override

    jdk1.6以后,接口的@Override就支持!

     

     

    9. 拦截器

    概念

    Interceptor 表示拦截器!

     

    1. Struts2通过一个拦截器完成一些通用的功能!用户使用哪些功能,自由组合即可!

    2. Struts2总共定义了32个拦截器

    Struts-defualt.xml中定义

    3. 拦截器栈

    引入一个个拦截器比较麻烦,可以定义一个栈里面包含多个拦截器;

    那么使用的时候,只需要引入拦截器栈即可!

    <interceptor-stack name="basicStack">

                    <interceptor-ref name="拦截器1"/>  引用的拦截器

                    <interceptor-ref name="拦截器1"/>

                    <interceptor-ref name="拦截器1"/>

    </interceptor-stack>

     

    4. 默认执行的拦截器栈

        defaultStack为默认执行的拦截器栈;里面共引用了18个拦截器!

    执行拦截器栈:

    <default-interceptor-ref name="defaultStack"/>

    注意:

    如果用户没有指定执行哪个拦截器栈,“默认栈”就会被执行!

    如果用户指定执行了哪个拦截器栈,默认的栈就不会被执行!

    defaultStack strtus的基本功能,一般开发都会用到!

     

    5. 面试题: 过滤器与拦截器区别?

    共同点: 拦截器请求!

    过滤器:

    Servlet中的概念,可以拦截器所有的请求!

    拦截器:

    Struts2中的概念,只能拦截strutsaction的请求!

     

     

    API & 配置

    ü API

    |-- interface Interceptor    拦截器接口!

    |--abstract class  AbstractInterceptor   一般开发,可以直接继承这个类即可!

     

    |-- interface   ActionInvocation   拦截器的执行状态

    拦截器的依次调用,使用的就是这个对象!

     

     

    接口核心3个方法:(filter类似)

    void

    destroy() 

     void

    init() 

     String

    intercept(ActionInvocation invocation) 

     

     

    ü 配置

    Struts-default.xml配置

     

    1. 定义拦截器

    <interceptors>

        

        1.1 定义每一个拦截器

        <interceptor name="abc" class=""/> 

        

        1.2 定义拦截器栈

        <interceptor-stack name="basicStack">

             <interceptor-ref name="abc"/>

        </interceptor-stack>

     

    </interceptors>

     

    2. 执行哪些拦截器(通过引用栈指定)

    <default-interceptor-ref name="basicStack"/>

     

     

    自定义拦截器

    步骤:

    1. 写一个普通java类,实现interceptor接口!

    2. struts.xml配置拦截器

     

    /**

     * 自定义拦截器

     * @author AdminTH

     *

     */

    public class HelloInterceptor implements Interceptor{

    // 启动时候,创建实例

    public HelloInterceptor(){

    System.out.println("1. 创建拦截器实例!");

    }

     

    // 启动后,创建实例之后执行初始化方法!

    @Override

    public void init() {

    System.out.println("2. HelloInterceptor.init()");

    }

     

    // 拦截器业务处理方法在访问时候执行?

    @Override

    public String intercept(ActionInvocation invocation) throws Exception {

    System.out.println("4. 拦截, 执行开始");

    // 放行(去到下一个拦截器,如果没有下一个拦截器,就进入action)

    String result = invocation.invoke();

    System.out.println("6. 拦截, 执行结束");

    return result;

    }

    @Override

    public void destroy() {

    System.out.println("销毁拦截器实例时候执行!");

    }

    }

     

    <?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="interceptor" extends="struts-default">

     <!-- 配置拦截器 -->

     <interceptors>

       <!-- 自定义的拦截器 -->

       <interceptor name="hello" class="cn.itcast.e_interceptor.HelloInterceptor"></interceptor>

       <!-- 定义拦截器栈 -->

       <interceptor-stack name="myStack">

        <!-- 引入默认的拦截器栈 -->

        <interceptor-ref name="defaultStack"></interceptor-ref>

        <!-- 自定义的拦截器 -->

    <interceptor-ref name="hello"></interceptor-ref>    

       </interceptor-stack>

     </interceptors>

     <!-- 执行自定义的拦截器栈 -->

     <default-interceptor-ref name="myStack"></default-interceptor-ref>

     

     <action name="user_*" class="cn.itcast.e_interceptor.UserAction" method="{1}">

    <result name="success">/test.jsp</result>

     </action>

     

    </package>

     

    </struts>

     

     

     

    执行流程

    服务器启动:

    1. 创建拦截器实例

    2. 执行init()初始化方法

    用户访问Action

    3. 创建Action实例

    4. 执行拦截器intercept()方法

    invocation.invoke();  表示进入下一个拦截器,或执行action

    5. 进入action的业务方法,如execute()方法

    6. execute()方法完成后,又一次回到执行各个拦截器

     

    ActionInvocation 用法

    // 拦截器业务处理方法在访问时候执行?

    @Override

    public String intercept(ActionInvocation invocationthrows Exception {

    System.out.println("4. 拦截, 执行开始");

    /*

     * 测试invocation的方法

     */

    //1. 获取ActionContext对象

    ActionContext ac = invocation.getInvocationContext();

    //2. 获取当前拦截的action对象!

    Object action = invocation.getAction();

    //3. 获取action对象的代理对象

    ActionProxy proxy = invocation.getProxy();

    System.out.println(proxy.getActionName());  // 配置中action名称,即访问路径一部分

    System.out.println(proxy.getMethod());      // 当前执行的方法!

    System.out.println(proxy.getNamespace());   // 名称空间

    String result = invocation.invoke();

    System.out.println("6. 拦截, 执行结束");

    return "error";

    }

     

     

    拦截器作用:

    action的请求进行拦截,从而处理一些公用的业务逻辑操作!

    那么action类中就可以直接用拦截器已经实现的功能了!

    案例

    1) 需求:

    只有登陆后的用户,才可以查看“用户列表”!

    功能:

    1. 登陆

    2. 列表展示

    3. 权限控制

    只有登陆,才能查看列表!

    2) 实现步骤:

    先做登陆、列表;

    再增加“登陆验证功能”!

     

    1. 环境准备

    建库建表

    项目使用组件

    # struts2

    # DbUtils组件

    # C3p0连接池

    # MySQL驱动包

    # JdbcUtils工具类

     

    2. entity 

    User.java

    3. dao

    UserDao.java

    Login();

    List()

    4. service

    5. action

    LoginAction

    UserAction

    6. login.jsp / list.jsp

     

    7. “拦截器”实现登陆验证!

    只有登陆后,才可以查看列表!

     

     

     

     

     

    -- 建库

    CREATE DATABASE day28 CHARACTER SET utf8;

     

    USE day28;

    day28

    -- 建表

    CREATE TABLE t_user(

      id INT PRIMARY KEY AUTO_INCREMENT,

      userName VARCHAR(20),

      pwd  VARCHAR(20),

      remark VARCHAR(200)

    );

    -- 录入测试数据

    INSERT INTO t_user VALUES(1,'jack','888','好人');

    INSERT INTO t_user VALUES(2,'rose','888','女人');

     

     

     

    方式1: 在action配置标签体中,引入拦截器

    拦截器代码:

     

    /**

     * 用户登陆验证拦截器

     * @author AdminTH

     *

     */

    public class UserInterceptor extends AbstractInterceptor {

     

    // 拦截器业务处理方法.....

    @Override

    public String intercept(ActionInvocation invocation) throws Exception {

    //1. 获取ActionContext

    ActionContext ac = invocation.getInvocationContext();

    //2. 获取登陆用户

    Object obj = ac.getSession().get("userInfo");

    //3. 判断

    if (obj == null) {

    // 没有登陆,不放行

    return "input";

    else {

    // 已经登陆,放行!

    return invocation.invoke();

    }

    }

     

    }

     

    Struts.xml

     

    <struts>

     

    <package name="user" extends="struts-default">

    <!-- 定义拦截器 -->

    <interceptors>

    <interceptor name="user" class="cn.itcast.interceptor.UserInterceptor"></interceptor>

    <interceptor-stack name="userStack">

    <!-- 指定栈中定义的拦截器:先引入默认栈,再引入自定义栈! -->

    <interceptor-ref name="defaultStack"></interceptor-ref>

    <interceptor-ref name="user"></interceptor-ref>

    </interceptor-stack>

    </interceptors>

    <!-- 全局视图 -->

    <global-results>

    <result name="input">/login.jsp</result>

    </global-results>

     

    <!-- 登陆 -->

    <action name="login" class="cn.itcast.action.LoginAction" method="login">

    <!-- 登陆成功,重定向到列表的action -->

    <result name="list" type="redirectAction">user_list.action</result>

    </action>

    <!-- 用户管理(列表展示、新增、修改等功能 -->

    <action name="user_*" class="cn.itcast.action.UserAction" method="{1}">

    <!-- 哪个action需要登陆验证,就引入相应的拦截器栈 -->

    <interceptor-ref name="userStack"></interceptor-ref>

    <result name="list">/WEB-INF/list.jsp</result>

    </action>

     

    </package>

     

    </struts>

     

     

     

    总结:

    哪个action需要登陆验证,就引入相应的拦截器栈, 比较麻烦!

     

     

     

    方式2:  使用全局拦截器引入方式

     

    //方式2

    @Override

    public String intercept(ActionInvocation invocation) throws Exception {

    /*

     * 不验证登陆!(或注册!)

     * 思路:

     *  拿到当前执行的方法,如果是“login”, 直接放行!

     *              如果不是"login", 验证

     */

    // 获取当前执行的方法名称

    String method = invocation.getProxy().getMethod();

    // 判断:如果是登陆方法,就放行

    if("login".equals(method)) {

    return invocation.invoke();

    }

    //1. 获取ActionContext

    ActionContext ac = invocation.getInvocationContext();

    //2. 获取登陆用户

    Object obj = ac.getSession().get("userInfo");

    //3. 判断

    if (obj == null) {

    // 没有登陆,不放行

    return "input";

    else {

    // 已经登陆,放行!

    return invocation.invoke();

    }

    }





  • 相关阅读:
    Golang数组Array
    转:【专题六】UDP编程
    转:【专题五】TCP编程
    转:【专题四】自定义Web浏览器
    转:【专题三】自定义Web服务器
    转:【专题二】HTTP协议详解
    转:【专题一】网络协议简介
    转:[你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单
    转:[你必须知道的异步编程]——基于任务的异步模式
    转:[你必须知道的异步编程]——基于事件的异步编程模式
  • 原文地址:https://www.cnblogs.com/dantefung/p/4830568.html
Copyright © 2011-2022 走看看