Struts2学习笔记

一. Struts2开发步骤:

1. 引入struts的jar包。

commons-fileupload-1.2.2.jar 文件上传相关包
commons-io-2.0.1.jar 文件上传相关包
commons-lang3-3.1.jar struts对java.lang包的扩展
freemarker-2.3.19.jar struts的标签魔般苦jar文件
javassist-3.11.0.GA.jar struts对子解码的处理相关jar
ognl-3.0.5.jar Ognl表达式功能支持表
struts2-core-2.3.4.1.jar struts2核心功能包
xwork-core-2.3.4.1.jar Xwork核心功能包

2. web.xml,引入structs的核心功能,配置过滤器
 StrutsPrepareAndExecuteFilter,这是2.1.8以后的核心,要注意不同版本的过滤器,是不一样的。

<code>

<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>
</code>
tomcat启动—>加载自身的web.xml—>加载所有项目的web.xml—>通过在项目的web.xml中引入过滤器
--》Struts的核心功能,通过过滤器完成
--》filter『
init/ 启动执行
doFilter/ 访问执行
destory

3. 开发action

action类,也叫动作类,用来处理请求,一般继承ActionSupport类,也可以实现Action接口,也可以什么都不做
业务方法返回值,必须为String,而且方法必须没有参数。

<code>
// 开发action:处理请求
public class HelloAction extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("访问到了action");
System.out.println("调用services");
return "success";
}
}
</code>

4. 配置action

在src/struts.xml配置
<code>
<?xml version="1.0" encoding="UTF-8" ?> // 编码
<!DOCTYPE struts PUBLIC // 文档类型声明,声明根结点为struts,资源来自于网络(PUBLIC)
<struts>
<package name="xxxx" extends="struts-default">
// 访问路径 访问的类 访问的类的方法
<action name="hello" class="com.ycTime.action.HelloAction" method="execute">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
</code>

二. struts2框架

预先实现功能:
1. 请求数据自动封装
如果在表单那里用的是对象的属性,比如user.userName,就可以将表单的数据封装成一个user对象
2. 文件上传功能
3. 对国际化功能的简化
4. 数据校验功能
。。。

struts执行流程:

  • 服务器启动:
  • 加载项目web.xml
  • 创建struts核心过滤器对象,执行filter—>init()
    struts-default.xml 核心功能的初始化
    sturts-plugin.xml struts相关插件
    struts.xml 用户编写的struts.xml
  • 访问:
  • 用户访问Action,服务器根据访问路径名称,访问相应的action类的相应方法
  • 后面的每次访问,都会创建action实例

struts中struts.xml:

  • include结点:引用其他文件,比如总配置文件中(struts.xml)将每一个包中的配置文件引进来
  • package结点,定义一个包,用于管理action,通常一个业务模板用一个包。
    • name:包名字,不能重复
    • extends:当前包继承自哪个包,在struts中,包一定要继承struts-default,struts-default在struts-default.xml中定义
    • abstruct:声明当前包为抽象包,只有当前包被继承的时候才使用,如果里面声明了action,则会在运行时报错
    • namespace:名称空间,默认为“/”,作为请求路径的一部分
  • action结点 配置请求路径与action类的映射关系
    • name 请求路径名称
    • class 请求处理的action类的全名
    • method 求情处理的方法
    • result
      • name action处理方法返回值
      • type 跳转的结果类型

三.struts的域操作

<code>
// 将数据保存到域
ActionContext context = ActionContext.getContext();
// 获得request的域的map
Map<String, Object> request = context.getContextMap();
// 获得session的域的map
Map<String, Object> session = context.getSession();
// 获得application的域的map
Map<String, Object> application = context.getApplication();
// 将数据保存到域中
request.put("request_data", "request_data");
session.put("session_data", "session_data");
application.put("application_data", "application_data");
</code>

四.通配符

在struts.xml里配置action时使用
<code>
<action name="user_*" class="com.ycTime.action.UserAction" method="{1}">
<result name="{1}" >/{1}.jsp</result>
</action>
</code>
*表示匹配任意字符串,{1}表示第一个位置的*,{n}表示第n个位置的*,除了method,在name那里也可以使用,在选择跳转到哪个页面都可以使用

五.struts常量

struts1中的默认访问后缀是*.do
struts2中的默认访问后缀是*.action

如何修改struts的后缀?

1.首先得知道.action是在哪里定义的?

   struts-core-2.3.4-1.jar/org.apache.struts/default.properties里面

2.修改方法
去struts.xml里配置
<code><constant name="struts.action.extension" value="action,do,,"></constant>
value="action,do," 可用后缀名为action,do,或者没有后缀名
value="action,do" 可用的后缀名只有action和do
value="action" 可用的后缀名只有action</code>

常用常量:

指定默认编码集,作用于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"/>

在action里面没有指定使用的method的时候,在访问url的时候用!接方法名就行了
<code><action name="user" class="com.ycTime.action.UserAction">
<result name="logout" >/success.jsp</result>
</action>
eg:http://127.0.0.1:8080/Fir_struts/user/user!logout
</code>
上传文件的大小限制
<code><constant name="struts.multipart.maxSize" value=“10701096"/></code>

六. 默认值

配置全局跳转:
<code><global-results>
<result name="success">/success.jsp</result>
</global-results></code>
要使用全局的跳转,必须在action那里没有配置跳转目的,这样才会去全局配置那里寻找,而且全局跳转必须放在每一个action的前面。


action的method的默认值:
<code><action name="default" class="com.ycTime.action.UserAction">
</action></code>
当action不配置方法的时候,action会默认执行action类里面的execute方法
<code><action name="default" >
</action></code>
当action连执行class都没指定,会默认使用下面的action类

<code><default-class-ref class="com.opensymphony.xwork2.ActionSupport" /></code>
×××
但是什么情况下使用不指定类的action呢?

    将action作为跳转中转站。可以用来访问WEB-INF下的页面啦。

但是要注意不能像下面那样
<code><action name="default" >
<result name="success" type="redirect">/WEB-INF/index.jsp </result>
</action></code>
type不能设置为重定向,可以像下面这样
<code><action name="default" >
<result name="success" >/WEB-INF/index.jsp </result>
</action></code>

七.数据处理

    // struts对数据的操作,方式一:直接拿到ServletApi,执行操作
    HttpServletRequest request = ServletActionContext.getRequest();
    HttpSession session = request.getSession();
    ServletContext application = ServletActionContext.getServletContext();
    
    request.setAttribute("request_data", "request_data");
    session.setAttribute("session_data", "session_data");
    application.setAttribute("application_data", "application_data");

    
    // struts对数据的操作,方式二:通过ActionContext
    ActionContext context = ActionContext.getContext();
    // Struts对HttpServletRequest对象进行了封装,封装成一个map
    
    Map<String, Object> request = context.getContextMap();
    
    Map<String, Object> session = context.getSession();
    
    Map<String, Object> application = context.getApplication();
    request.put("request_data", "request_data");
    session.put("session_data", "session_data");
    application.put("application_data", "application_data");

    方式一和方式二的不同在于,方式一用的是servlet的方式,需要引用servlet的包。但当遇到方式二实现不了的情况,就要用回第一种,比如获取当前项目目录


/**
 * 方式三:实现接口
 * @author root
 *
 */
public class DataAction implements   Action,RequestAware,SessionAware,ApplicationAware {

private Map<String, Object> request;
private Map<String, Object> session;
private Map<String, Object> application;
@Override
public void setRequest(Map<String, Object> request) {
    this.request = request;
}

@Override
public void setSession(Map<String, Object> session) {
    this.session = session;
}

@Override
public void setApplication(Map<String, Object> application) {
    this.application = application;
}

第三种方式适合action中存在很多的业务方法。一般来说,我们可以弄一个basection,然后将接口实现,以后每一个继承baseaction的action,都可以直接使用那些对象。

八.文件上传及下载

文件上传

servlet的文件上传:

  • 前端页面:
    1.必须为post请求
    2.表单类型为multipart/form-data
    3.input type="file"
  • 后台:
    使用FileUpLoad组件
    核心类:
    FileItemFactory FileItem的工厂
    ServletFileUpload servlet中文件上传的核心类
    FileItem 封装了上传的表单文件项的信息

struts的文件上传:
前端表单:
<code><form action="${pageContext.request.contextPath }/fileUploadAction" method="post" enctype="multipart/form-data">
用户名<input type="text" name="username" />

文件<input type="file" name="file1" / >

<input type="submit" name="提交"/ >
</form></code>
后台action:
<code>
public class FileUploadAction extends ActionSupport {
// 只有file1是不确定的,FIleName,ContentType都是固定的
private File file1;
private String file1FileName;
private String file1ContentType;
public void setFile1(File file1) {
this.file1 = file1;
}
public void setFile1FileName(String file1FileName) {
this.file1FileName = file1FileName;
}
public void setFile1ContentType(String file1ContentType) {
this.file1ContentType = file1ContentType;
}
@Override
public String execute() throws Exception {
// 获取上传的目录路径
String path =ServletActionContext.
getServletContext().getRealPath("/media");
// 创建目标文件对象
File destFile = new File(path,file1FileName);
// 把上传的文件,拷贝到目标文件中
FileUtils.copyFile(file1, destFile);
System.out.println(file1);
System.out.println(file1FileName);
return SUCCESS;
}
}</code>


文件上传的细节:

  • 文件大小限制
    struts默认支持的最大的上传的文件大小为2M
    要修改的话通过常量修改
  • 错误提示
    当上传文件出现错误,action就会返回一个“input”,这个时候我们应该配置一个input的错误页面
    <code>

    <result name="input">/error.jsp</result></code>
  • 限制文件类型
    在处理文件上传的action那里设置
    <code>
    <interceptor-ref name="defaultStack">

    <param name="fileUpload.allowedExtensions">jpg,txt</param>
    </interceptor-ref></code>
  • 限制允许的文件类型
    <code>
    <param name="fileUpload.allowedTypes">text/plain</param></code>
    一般这两个方法不一起使用

文件下载:

action里面的配置:
<code>
// 1. 获取要下载的文件的文件名
private String fileName;
public void setFileName(String fileName) {
// 处理传入的参数中问题(get提交)
System.out.println("fileName:"+fileName);
try {
fileName = new String(fileName.getBytes(),"utf-8");
} catch (UnsupportedEncodingException e) {
System.out.println(e.getMessage());
throw new RuntimeException(e);
}
// 把处理好的文件名,赋值
this.fileName = fileName;
}
//2. 下载提交的业务方法 (在struts.xml中配置返回stream)
public String down() throws Exception {
return "download";
}
// 3. 返回文件流的方法
public InputStream getAttrInputStream(){
return ServletActionContext.getServletContext().getResourceAsStream("/media/" + fileName);
}
// 4. 下载显示的文件名(浏览器显示的文件名)
public String getDownFileName() {
// 需要进行中文编码
String downFileName = fileName;
try {
downFileName = new String(downFileName.getBytes(), "ISO8859-1");

    } catch (UnsupportedEncodingException e) { 
    e.printStackTrace(); 
    } 
    System.out.println("downFileName"+downFileName);
    return downFileName; 
}</code>

struts.xml里的配置:
<code><action name="down_*" class="com.ycTime.action.FileUploadAction" method="{1}">

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

<result name="download" type="stream">

<param name="contentType">application/octet-stream;charset=ISO8859-1</param>
// 后面那个charset至关重要,就是因为没了这个东西,网页上能看见文件,但是下载显示的文件名一直都是乱码

<param name="inputName">attrInputStream</param>

<param name="contentDisposition">
attachment;filename=${downFileName}
</param>

<param name="bufferSize">1024</param>
</result>
</action>
</code>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容

  • 概述 Struts就是基于mvc模式的框架!(struts其实也是servlet封装,提高开发效率!) Strut...
    奋斗的老王阅读 2,933评论 0 51
  • GitHub 地址 访问GitHub下载最新源码:https://github.com/JYG0723/Strut...
    HikariCP阅读 276评论 0 2
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • 概述 什么是Struts2的框架Struts2是Struts1的下一代产品,是在 struts1和WebWork的...
    inke阅读 2,249评论 0 50
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,605评论 18 399