(二)、Struts第二天
(二)、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类似)
|
ü 配置
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第二天的更多相关文章
- python学习笔记之基础二(第二天)
1.编码转换介绍 unicode是最底层.最纯的,会根据终端的编码进行转化展示 一般硬盘存储或传输为utf-8(因为省空间.省带宽),读入内存中为unicode,二者如何转换 a = ' ...
- #Java学习之路——基础阶段二(第二篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- 广州商学院16级软工一班&二班-第二次作业成绩
作业地址 https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2097 https://edu.cnblogs.com/campus/gzc ...
- Alpha冲刺随笔二:第二天
课程名称:软件工程1916|W(福州大学) 作业要求:项目Alpha冲刺(十天冲刺) 团队名称:葫芦娃队 作业目标:在十天冲刺里对每天的任务进行总结. 随笔汇总:https://www.cnblogs ...
- The Definitive Guide To Django 2 学习笔记(二) 第二个View 动态内容
“Hello World”只是简单的展现了Django 基本的工作机制,但它不是动态的网页.第二个View我们将创建一个动态的网页,该页面上将展现当前的时间和日期. 该View需要做两件事,第一,计算 ...
- SAP标准培训课程C4C10学习笔记(二)第二单元
第二单元目录: SAP Cloud for Customer的项目实施分为4个阶段: 这四个阶段的详细介绍在SAP社区上这篇博文里: SAP Hybrid Project implementation ...
- 大二暑假第二周总结--开始学习Hadoop基础(一)
一.简单视频学习Hadoop的处理架构 二.简单视频学习分布式文件系统HDFS并进行简单的实践操作 简单操作教程:http://dblab.xmu.edu.cn/blog/290-2/ 注意:在建立H ...
- 程序设计实习MOOC / 程序设计与算法(二)第二周测验(2018春季)
递归算法: 1:全排列 总时间限制: 1000ms 内存限制: 65536kB 描述 给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列. 我们假设对于小写字母有'a' < ' ...
- 《深入理解Spark-核心思想与源码分析》(二)第二章Spark设计理念和基本架构
若夫乘天地之正,而御六气之辩解,以游无穷者,彼且恶乎待哉? ——<庄子.逍遥游> 翻译:至于遵循宇宙万物的规律,把握“六气”的变化,遨游于无穷无尽的境域,他还仰赖什么呢! 2.1 初始Sp ...
随机推荐
- C - 小Y上学记——认识新同学
C - 小Y上学记——认识新同学 Time Limit: 4000/2000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) ...
- 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 ...
- UIAlertAction 弹出对话框9.0后有点变化
ios 9.0后再用以前的UIAlertAction 已经不行了 被弃用了 改用这种方法了 UIAlertController *alertController = [UIAlertControlle ...
- bootstrap validator html attributes 选项
常用的html属性:data-fv-message="The username is not valid"data-fv-notempty="true"data ...
- LibRTMP优化之调整输出块大小
1. 为什么要调整输出块大小 首先在RTMP_Connect0函数中LibRTMP是关闭了Nagle算法这个TCP选项的,为了实时性这样做是好的,但是要注意到LibRTMP的结构体RTMP的成员是有m ...
- 深入理解JNI(《深入理解android》(author : 邓凡平)读书札记)
JNI的技术特点: java能够调用native代码. native代码能够调用java代码. JNI的技术考虑: 实现java代码的平台无关型. java语言发展初期使用C和C++代码,避免重复 ...
- 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 ...
- Linux 配置tomcat遇见的若干问题
1.提示catalina.sh缺失 原因:未对bin目录下的.sh文件授权 执行:chmod +x bin/*.sh即可 2.正常启动Tomcat 但是外界无法访问 Linux防火墙原因,进入到 et ...
- php的错误和异常处理
php中try catch的例子: <?php try { if (@mysql_connect('localhost','root','123456')){ // echo 'success! ...
- HTML+CSS D08浮动
1. <html> <head> <title>div浮动</title> <style type="text/css"> ...