(二)、Struts第二天

回顾:

问题:

1. Struts2的Action类是单例还是多例? 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>        同上

方式2:http://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=" "/>

指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法 和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. 数据处理

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

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

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

RequestAware/SessionAware/ApplicationAware

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

方式3:ServletActionContext 获取原始的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会把表示request的map注入进来!

@Override

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

this.request = request;

}

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

@Override

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

this.session = session;

}

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

@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中的概念,只能拦截struts的action的请求!

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 invocation) throws 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();

}

}

(二)、Struts第二天的更多相关文章

  1. python学习笔记之基础二(第二天)

    1.编码转换介绍        unicode是最底层.最纯的,会根据终端的编码进行转化展示 一般硬盘存储或传输为utf-8(因为省空间.省带宽),读入内存中为unicode,二者如何转换 a = ' ...

  2. #Java学习之路——基础阶段二(第二篇)

    我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...

  3. 广州商学院16级软工一班&二班-第二次作业成绩

    作业地址 https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2097 https://edu.cnblogs.com/campus/gzc ...

  4. Alpha冲刺随笔二:第二天

    课程名称:软件工程1916|W(福州大学) 作业要求:项目Alpha冲刺(十天冲刺) 团队名称:葫芦娃队 作业目标:在十天冲刺里对每天的任务进行总结. 随笔汇总:https://www.cnblogs ...

  5. The Definitive Guide To Django 2 学习笔记(二) 第二个View 动态内容

    “Hello World”只是简单的展现了Django 基本的工作机制,但它不是动态的网页.第二个View我们将创建一个动态的网页,该页面上将展现当前的时间和日期. 该View需要做两件事,第一,计算 ...

  6. SAP标准培训课程C4C10学习笔记(二)第二单元

    第二单元目录: SAP Cloud for Customer的项目实施分为4个阶段: 这四个阶段的详细介绍在SAP社区上这篇博文里: SAP Hybrid Project implementation ...

  7. 大二暑假第二周总结--开始学习Hadoop基础(一)

    一.简单视频学习Hadoop的处理架构 二.简单视频学习分布式文件系统HDFS并进行简单的实践操作 简单操作教程:http://dblab.xmu.edu.cn/blog/290-2/ 注意:在建立H ...

  8. 程序设计实习MOOC / 程序设计与算法(二)第二周测验(2018春季)

    递归算法: 1:全排列 总时间限制:  1000ms 内存限制:  65536kB 描述 给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列. 我们假设对于小写字母有'a' < ' ...

  9. 《深入理解Spark-核心思想与源码分析》(二)第二章Spark设计理念和基本架构

    若夫乘天地之正,而御六气之辩解,以游无穷者,彼且恶乎待哉? ——<庄子.逍遥游> 翻译:至于遵循宇宙万物的规律,把握“六气”的变化,遨游于无穷无尽的境域,他还仰赖什么呢! 2.1 初始Sp ...

随机推荐

  1. C - 小Y上学记——认识新同学

    C - 小Y上学记——认识新同学 Time Limit: 4000/2000MS (Java/Others)    Memory Limit: 128000/64000KB (Java/Others) ...

  2. ural 1353. Milliard Vasya's Function(dp)

    1353. Milliard Vasya's Function Time limit: 1.0 second Memory limit: 64 MB Vasya is the beginning ma ...

  3. UIAlertAction 弹出对话框9.0后有点变化

    ios 9.0后再用以前的UIAlertAction 已经不行了 被弃用了 改用这种方法了 UIAlertController *alertController = [UIAlertControlle ...

  4. bootstrap validator html attributes 选项

    常用的html属性:data-fv-message="The username is not valid"data-fv-notempty="true"data ...

  5. LibRTMP优化之调整输出块大小

    1. 为什么要调整输出块大小 首先在RTMP_Connect0函数中LibRTMP是关闭了Nagle算法这个TCP选项的,为了实时性这样做是好的,但是要注意到LibRTMP的结构体RTMP的成员是有m ...

  6. 深入理解JNI(《深入理解android》(author : 邓凡平)读书札记)

    JNI的技术特点: java能够调用native代码. native代码能够调用java代码.   JNI的技术考虑: 实现java代码的平台无关型. java语言发展初期使用C和C++代码,避免重复 ...

  7. split a string in C++

    This is my favourite way to iterate through a string. You can do what you want per word. string line ...

  8. Linux 配置tomcat遇见的若干问题

    1.提示catalina.sh缺失 原因:未对bin目录下的.sh文件授权 执行:chmod +x bin/*.sh即可 2.正常启动Tomcat 但是外界无法访问 Linux防火墙原因,进入到 et ...

  9. php的错误和异常处理

    php中try catch的例子: <?php try { if (@mysql_connect('localhost','root','123456')){ // echo 'success! ...

  10. HTML+CSS D08浮动

    1. <html> <head> <title>div浮动</title> <style type="text/css"> ...