Java自学手记——struts2
struts2框架
struts2是一种基于MVC模式的框架,是在struts1的基础上融合了xwork的功能。
struts2框架预处理了一些功能:
>请求数据自动封装,
>文件上传的功能
>对国际化功能的简化
>数据校验功能
使用struts2框架开发的流程:
1.引入jar文件
>commons-fileupload-1.2.2.jar 【文件上传相关包】
>commons-io-2.0.1.jar
>struts2-core-2.3.4.1.jar 【struts2核心功能包】
>xwork-core-2.3.4.1.jar 【Xwork核心包】
>ognl-3.0.5.jar 【Ognl表达式功能支持表】
>commons-lang3-3.1.jar 【struts对java.lang包的扩展】
>freemarker-2.3.19.jar 【struts的标签模板库jar文件】
>javassist-3.11.0.GA.jar 【struts对字节码的处理相关jar】
2.配置web.xml
Tomcat启动时,会加载所有项目的web.xml,通过web.xml中引入过滤器,而struts的核心功能
的初始化,是通过过滤器完成的
<!--引入核心过滤器-->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
StrutsPrepareAndExecuteFilter就是核心过滤器,位于struts2的核心功能包中,使用struts版本不同,核心过滤器类是不一样的
3.配置struts.xml
struts2的执行流程
1.服务器启动
>加载web.xml
>创建struts核心过滤器对象,执行filter-->init()
·struts-default.xml, 核心功能的初始化
·struts-plugin.xml, struts相关插件
·struts.xml 用户编写的配置文件
2.用户访问
>用户访问action,服务器根据路径名称,找对应的action配置,创建action对象
>执行默认拦截器栈中定义的18个拦截器
>执行action的业务处理方法
struts-default.xml详解
1.位于struts2-core-2.3.jar包中,
2.bean节点指定了struts在运行时候创建的对象类型
3.指定struts-default包,用户写的struts.xml文件中package一定要继承此包,struts-default包定义了:
>跳转的结果类型:dispatcher,redirect,redirectAction,stream
>定义了所有拦截器,一共32个拦截器,为了拦截器引用方便,可以通过定义栈的方式引用拦截器,默认的栈中包含了初始化18个拦截器
>默认执行的拦截器栈、默认执行的action
拦截器和过滤器比较:
相似:功能相似
区别: 过滤器,拦截器所有资源都可以; (/index.jsp/servlet/img/css/js)
拦截器,只拦截action请求。
拦截器是struts的概念,只能在struts中用。
过滤器是servlet的概念,可以在struts项目、servlet项目用
注意:拦截器什么时候执行,先执行Action类创建,还是先执行拦截器
答:拦截器在访问时执行,先创建Action类对象,再按顺序执行18个拦截器,最后执行Action类的业务处理方法
Action开发
Action开发有三种方式:
1.继承ActionSupport类,如果用struts的数据校验功能,必须继承此类
2.实现Action接口,重写execute方法
3.不继承任何类,不实现任何接口
struts中路径匹配原则:
localhost:访问到哪一台机器
8080:找到Tomcat
mystruts:找到项目名
/user/a/b:查找是否有此名称空间,没有则向下
/user/a:查找是否有此名称空间,没有则向下
/user:查找是否有此名称空间,没有则向下
/:查找是否有此名称空间,没有则报错
例如:<action name="login" class="..." method="..."></action>,项目名称后面可以有/a/b这些无用的分层,只要最后为login以及名称空间正确照样能访问
struts中的常量
>struts中的常量定义了默认访问后缀等配置,文件名为default.propertities
>位于struts核心包中
>能够在struts.xml中通过<constant name="key" value="value"></coonstant>修改默认常量配置
struts中对数据操作(三种方式)
1.直接拿到servletAPI,进行操作,核心类:ServletActionContext提供的静态方法
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
ServletContext application = ServletActionContext.getServletContext();
2.通过ActionContext类获取(代表request,session,application)map
ActionContext ac = ActionContext.getContext();
//struts对HttpServletRequest进行了封装,封装成一个map //拿到表示request对象的map
Map<String, Object> request = ac.getContextMap(); //拿到session对象的map
Map<String, Object> session = ac.getSession(); //拿到表示ServletContext对象的map
Map<String, Object> application = ac.getApplication();
3.实现接口的方式:(requestAware/sessionAware/applicationAware)
public class DataAction2 extends ActionSupport implements RequestAware,
SessionAware, ApplicationAware {
Map<String, Object> request;
Map<String, Object> session;
Map<String, Object> application; // struts运行时,会把代表request的map对象注入
@Override
public void setRequest(Map<String, Object> request) {
this.request = request;
} // struts运行时,会把代表session的map对象注入
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
} // struts运行时,会把代表application的map对象注入
@Override
public void setApplication(Map<String, Object> application) {
this.application = application;
} @Override
public String execute() throws Exception {
request.put("request_data", "request_actionAware");
session.put("session_data", "session_actionAware");
application.put("application_data", "application_actionAware"); return SUCCESS;
}
}
区别:第二种方式由于不用引进servlet包,是解耦的方式实现对数据的操作,所以推荐使用第二种方式
但是,第二种方式每个事务方法都要获取ActionContext,因为ActionContext可以获取struts的数据或者对象,而这一过程
是通过拦截器完成的,而拦截器在创建Action对象之后运行,所以无法把ActionContext对象在全局变量中获取,第二种和第三种
方式原理一样,不过第三种方式通过接口则解决了第二种方式的不足,但实现起来较麻烦,业务方法比较多的时候应该优先考虑。
第一种方式可以在二三种方式无法实现需求是使用比如获取request.getContextPath()等。
struts2中请求数据自动封装(两种方式)
实现原理:参数拦截器,用户访问时,创建了Action对象,因此拦截器能够拿到action对象和属性
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
1.jsp表单数据填充到action中的属性,需要给出属性的set方法
2.jsp表单数据填充到action的对象中的属性:一定要给出对象的set和get方法
// 第一种方式
/*
* private String username;// 请求数据封装,必须给出set方法
* private String password;
* private int age;
* private Date birth;
*
* public void setUsername(String username) { this.username = username; }
*
* public void setPassword(String password) { this.password = password; }
*
* public void setAge(int age) { this.age = age; }
*
* public void setBirth(Date birth) { this.birth = birth; }
*/ // 第二种方式
private User user; public void setUser(User user) {
this.user = user;
} // 处理注册请求
public String regist() {
System.out.println("username:" + user.getUsername() + ",password:"
+ user.getPassword() + ",age:" + user.getAge() + ",birth:"
+ user.getBirth());
return SUCCESS;
}
数据类型转换
struts中jsp提交的数据,会自动转换为action中的属性的类型
对于基本类型以及日期类型会自动转换,日期类型只支持yyyy-MM-dd格式
如果是其他格式,需要自定义类型转换器
自定义类型转换器:
struts中转换器API
|--TypeConverter 转换器接口
|--DefaultTypeConverter 默认类型转换器(yyyy-MM-dd就是在这里定义的)
|--StrutsTypeConverter 用户编写的类型转换器,继承此类即可
局部转换器开发步骤:
1.写转换器类,重写父类的抽象方法
2.配置转换器类(告诉struts使用自定义的转换器类)
-->在同包的action目录下,新建一个properties文件
-->命名规则:ActionClassName-conversion.properties
举例:cn.electhuang.d_type/UserAction-conversion.properties
-->配置文件内容:user.birth=转换器类全路径(cn.electhuang.d_type.MyConverter)
总结:转换器(转换器类和配置文件)不能给其他Action用
全局类型转换器
需要写一个转换器给所有的action用
配置:
-->在src目录下,新建一个properties文件
-->命名规则:xwork-conversion.properties
-->内容:类型全名=转换器类(java.util.Date=cn.electhuang.d_type.MyConverter)
转换器类代码示例:
public class MyConverter extends StrutsTypeConverter {
// 要求支持三种Date格式
// 先定义格式
DateFormat[] df = { new SimpleDateFormat("yyyy-MM-dd"),
new SimpleDateFormat("yyyyMMdd"),
new SimpleDateFormat("yyyy年MM月dd日") }; /**
* 把String转换为指定类型
*
* @param context
* 当前上下文环境
* @param values
* jsp提交的字符串值
* @param toClass
* 要转换的目标类型
* @return the converted object
*/
@Override
public Object convertFromString(Map context, String[] values, Class toClass) { if (values == null || values.length == 0) {
return null;
}
System.out.println("1111");
if (Date.class != toClass) {
return null;
}
System.out.println("2222");
for (int i = 0; i < df.length; i++) {
try {
return df[i].parse(values[0]);
} catch (ParseException e) {
continue;
}
}
System.out.println("3333");
return null;
} @Override
public String convertToString(Map context, Object o) {
return null;
} }
struts文件上传
1.回顾采用servlet文件上传
前台:
-->提交方式必须为POST
-->表单类型:multipart/form-data
-->input type="file"
后台:
-->Apache提供的FileUpload组件
-->核心类:
①FileItemFactory FileItem的工厂
②ServletFileUpload servlet中文件上传的核心类
③FileItem 封装了上传的表单文件项的信息
总结:文件上传使用比较多,但处理比较麻烦!
2.struts的文件上传
文件上传拦截器帮助完成文件上传的功能
<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
代码示例:
public class FileUpload extends ActionSupport {
private File file1;// 对应表单的name
private String File1FileName;// 文件名
private String file1ContentType;// 文件类型 public void setFile1(File file1) {
this.file1 = file1;
} public void setFile1FileName(String file1FileName) {
File1FileName = file1FileName;
} public void setFile1ContentType(String file1ContentType) {
this.file1ContentType = file1ContentType;
} @Override
public String execute() throws Exception {
// 拿到上传文件进行处理
// 把文件上传到upload目录
// 获取上传的目录路径
String path = ServletActionContext.getServletContext().getRealPath(
"/upload"); // 创建目标文件对象
File destFile = new File(path, File1FileName); // 把上传的文件拷贝到目标文件对象中
FileUtils.copyFile(file1, destFile); return SUCCESS;
} }
重要:文件上传细节处理
-->文件大小限制:struts2默认支持上传最大是2M,可通过常量修改
当文件上传出现错误时,struts内部会返回input视图(错误视图),所以需要在struts.xml中配置input视图对应的错误页面
<!-- 4. 修改上传文件的最大大小为30M -->
<constant name="struts.multipart.maxSize" value="31457280"/>
-->限制上传文件的运行类型
拦截器注入参数从而限制文件上传类型
<!-- 限制上传文件的类型 -->
<interceptor-ref name="defaultStack">
<!-- 限制文件扩展名 -->
<param name="fileUpload.allowedExtensions">txt,jpg</param>
</interceptor-ref>
struts文件下载(2种方式)
1.通过response对象向浏览器写入字节流数据,设置下载的响应头
2.struts的方式
代码示例:
public class DownAction extends ActionSupport {
// 显示所有要下载的文件列表
public String list() {
// 得到upload目录
String path = ServletActionContext.getServletContext().getRealPath(
"/upload");
// 创建目录对象
File file = new File(path);
// 得到所有文件名
String[] fileNames = file.list();
// 保存
ActionContext ac = ActionContext.getContext();
Map<String, Object> request = ac.getContextMap();
request.put("fileNames", fileNames);
return "list";
} /*
* 文件下载
*/
// 1.获取要下载的文件名
private String fileName; public void setFileName(String fileName) {
try {
// 处理传入参数中文乱码问题
fileName = new String(fileName.getBytes("ISO8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
// 把处理好的文件名赋给fileName
this.fileName = fileName;
} // 2.下载提交的业务方法,需要在struts.xml中配置返回stream
public String down() {
return "download";
} // 3.返回流
public InputStream getAttrInputStream() { return ServletActionContext.getServletContext().getResourceAsStream(
"/upload/" + fileName);
} // 下载显示的文件名
public String getDownFileName() {
// 需要中文编码
try {
fileName = URLEncoder.encode(fileName, "utf-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return fileName;
}
}
配置文件配置方法:
<struts>
<package name="fileupload_" namespace="/" extends="struts-default" abstract="flase">
<!-- action的名称不要用FileUpload -->
<action name="fileUpload_" class="cn.electhuang.e_fileupload.FileUpload" method="execute">
<result name="success">/e/success.jsp</result> <!-- 配置错误视图 -->
<result name="input">/e/error.jsp</result> <!-- 限制上传文件的类型 -->
<interceptor-ref name="defaultStack">
<!-- 限制文件扩展名 -->
<param name="fileUpload.allowedExtensions">txt,jpg</param>
</interceptor-ref>
</action> <action name="down_*" class="cn.electhuang.e_fileupload.DownAction" method="{1}">
<!-- 列表展示 -->
<result name="list">/e/list.jsp</result> <!-- 下载操作 -->
<result name="download" type="stream">
<!-- 允许下载的文件类型,指定为所有的二进制文件类型 -->
<param name="contentType">application/octet-stream</param> <!-- 对应action中的属性,返回流的属性 ,其实就是找到getArrrInputStream方法-->
<param name="inputName">attrInputStream</param> <!-- 下载头,包括浏览器显示的文件,其实就是找到getDownFileName方法 -->
<param name="contentDisposition">attachment;filename=${downFileName}</param> <!-- 缓冲区大小设置 -->
<param name="bufferSize">1024</param>
</result>
</action> </package>
</struts>
Java自学手记——struts2的更多相关文章
- Java自学手记——Java中的关键字
Java中的一些关键字对于初学者来说有时候会比较混乱,在这里整理一下,顺便梳理一下目前掌握的关键字. 权限修饰符 有四个,权限从大到小是public>protected>defaul(无修 ...
- Java自学手记——接口
抽象类 1.当类和对象被abstract修饰符修饰的时候,就变成抽象类或者抽象方法.抽象方法一定要在抽象类中,抽象类不能被创建对象,如果需要使用抽象类中的抽象方法,需要由子类重写抽象类中的方法,然后创 ...
- Java自学手记——servlet3.0新特性
servlet3.0出来已经很久了,但市场上尚未普遍应用,servlet3.0有三个比较重要的新特性:使用注解来代替配置文件,异步处理以及上传组件支持. 支持servlet3.0的要求:MyEclip ...
- Java自学手记——注解
注意区分注释和注解,注释是给人看的,注解是给程序看的. 注解的作用是代替配置文件,在servlet3.0中,就可以不再使用web.xml文件,而是所有配置都是用注解!比如注解类 @WebServlet ...
- Java自学手记——泛型
泛型在集合中的应用 泛型在集合经常能看到,有两个好处:1.把运行时出现 的问题提前至了编译时:2.避免了无谓的强制类型转换. 用法:两边泛型的类型必须相同,可允许一边不写,只是为了兼容性,并不推荐. ...
- Java自学手记——集合
- Java自学手记——多态
对象转型 学习多态前先明白一个叫对象转型的概念,如: class Animal{ void sleep(){ System.out.println("睡觉"); } } class ...
- Java自学路线
万事开头难,学习Java亦是如此.而在学习的开始,选择正确的学习路线更是尤为重要.在本文中我将分享本人自学转行路上的学习路线,希望能给想自学,却不知道方向的同学带来帮助~ 1 .JavaSE 基础 这 ...
- 【转】JAVA自学之路
JAVA自学之路 一: 学会选择 为了就业,不少同学参加各种各样的培训. 决心做软件的,大多数人选的是java,或是.net,也有一些选择了手机.嵌入式.游戏.3G.测试等. 那么究竟应该选择什么方向 ...
随机推荐
- Amazing ASP.NET Core 2.0
前言 ASP.NET Core 的变化和发展速度是飞快的,当你发现你还没有掌握 ASP.NET Core 1.0 的时候, 2.0 已经快要发布了,目前 2.0 处于 Preview 1 版本,意味着 ...
- 基于底层的 XML 的解析方式详解
在上一篇博客中,我们介绍了什么是 XML ,http://www.cnblogs.com/ysocean/p/6901008.html,那么这一篇博客我们介绍如何来解析 XML . 部分文档引用:ht ...
- 我来谈谈PHP和JAVA的区别
这里的标题写的是谈谈PHP和JAVA的区别,其实是委婉的说法,其实别人是想听PHP好还是JAVA好!!! 从而从中找到存在感!!! 因为由于我是从多年的php开发转到java开发的.所以最,不时的有好 ...
- 1.Node.js 接入微信公众平台开发
一.写在前面的话 Node.js是一个开放源代码.跨平台的JavaScript语言运行环境,采用Google开发的V8运行代码,使用事件驱动.非阻塞和异步输入输出模型等技术来提高性能,可优化应用程 ...
- vue2.0+element+node+webpack搭建的一个简单的后台管理界面
闲聊: 今天是六一儿童节哟,小颖祝大家节日快乐哈哈哈.其实这个demo小颖断断续续做了将近两个礼拜了,心塞的,其实这个也没有多难,主要是小颖有点最近事情有点多,所以就把这个一直拖着,今天好不容易做好了 ...
- ReactNative学习之Html基础
前言: React Native开发作为一种新型的移动开发方式,个人觉得App的一部分需求会逐步替换成这种方式,也是公司移动开发人员所必须掌握的一种开发技术,所以鉴于这种情况我觉得很有必要学习一下,特 ...
- Python环境安装及基本概念
1.安装Python ①官网下载Python包安装 ②添加环境变量(新版Python包可直接添加环境变量) 手动添加环境变量:控制面板-系统-高级系统设置-环境变量-编辑Path添加python安装目 ...
- CSS小技巧-煎蛋的画法~
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- D. 实验室传染病
D. 实验室传染病 题意 给出 n 个人的位置,以及每个人的传染范围,当一个人患病时,他的传染范围内(包括边界上)的人全部会被感染并继续向外传播. 求以每个人为传染源最多有多少人被感染. 分析 首先二 ...
- NodeMCU透传数据到TcpServer和Yeelink平台
准备工作 1. NodeMCU LUA ESP8266 CP2102 WIFI Internet Development Board,仔细看背面可以看出自带cp2102模块,可以通过普通的手机充电 ...