Struts2--day03

非本人总结的笔记,抄点笔记复习复习。感谢传智博客和黑马程序猿


记笔记啊记笔记

Struts2国际化

什么是国际化

比如做一个软件,但是做软件,不仅中国人可以使用,其他国家的人也可以使用。根据操作系统的语言,自动识别显示的语言类型。
现在使用国际化,完成的功能是:比如如果进行表单校验功能,校验失败提示错误信息,系统是英文则提示英文;中文则提示中文。

国际互基本实现(配置全局国际化)

创建一系列配置资源文件,命名规范:基本名称_小写的语言_大写的国家.properties
比如:messaage_zh_CN.properties和message_en_US.properties
本地系统是中文系统,读取到message_zh_CN.properties文件的内容

Struts2实现国际化

前提:创建一系列资源文件


资源文件

所有的资源文件key值要相同

第一种:全局国际化(重点)

配置全局国际化,在项目中的action、jsp页面中、校验文件中,都可以获取国际化内容

实现的方式:通过Struts2的常量配置全局国际化

struts.custom.i18n.resources常量配置的值是资源文件的基本名称。如果资源文件在src下,直接写基本名称;如果资源文件在包里面,加上包路径com/xxx/xxx

<!--配置全局国际化-->
<constant name="struts.custom.i18n.resources" value="message"></constant>
  1. 在action里面读取国际化资源文件内容

    //方法中的值 资源文件中key的名称
    String value = this.getText("namekey");
    
    资源文件内容
  2. 在jsp中读取国际化资源文件内容

    <!--读取全局国际化资源文件内容,使用struts2的标签读取-->
    <s:text name="namekey"></s:text>
    

    text标签,name属性值,资源文件中key的名称

  3. 在xml校验文件中读取

    <validators>
     <field name="username">
             <field-validator type="requiredstring">
                 <massage key="namekey"></massage>
             </field-validator>
         </field>
    </validators>
    

第二种:action范围国际化

只能在某一个action中获取到资源文件内容

示例

在action所在包里面创建资源文件,命名:action类名_小写语言_大写语言.properties

获取示例

String value = this.getText("actionkey");

第三种:package范围国际化

在包里面的所有的action可以获取到资源文件内容

文件结构示例

在包里面创建资源文件,命名 基本名称必须是package

第四种:临时国际化(jsp获取资源文件内容)

在jsp页面中,获取package.properties资源文件内容

<!--struts2标签i18n标签-->
<s:i18n name="cn/itcast/message/package">
    <s:text name="packagekey"></s:text>
</s:i18n>

Struts2的拦截器

介绍

使用Struts2操作发送请求,首先到过滤器里面,过滤器解析xml,acting匹配操作,在执行action之前,做执行一系列的拦截器,这些拦截器是Struts2帮实现的一些功能的封装,在Struts2里面默认执行的拦截器在struts-default.xml,273行配置默认值执行的拦截器

Struts2的拦截器底层使用两部分原理

第一个:aop思想(Aop面向方面编程(切面))

比如有登录的功能,基本操作是输入表单数据,提交到Servlet中,判断用户名密码是否正确,最终如果正确到主页面,如果错误到登录页面,上面是登录到基本逻辑。

Aop表示在基本功能之上添加一个额外的功能,实时添加功能,这个功能如果不添加,基本功能也可以运行。

Aop面向方面编程

第二种 责任链模式

学过过滤器,有过滤链,一个请求可以有多个过滤器进行过滤,每个过滤器只有做放行才能到下一个过滤器

责任链模式:在一条线有一组操作,执行这些操作,但是每个操作执行完成之后,做类似于放行操作,才能执行下一个方法。

责任链模式执行过程

查看Struts2关于拦截器源代码

查看Struts2的过滤器

StrutsPrepareAndExecuteFilter

过滤器里面有init方法,加载配置文件

doFilter方法,做过滤操作

execute.executeAction(request, response, mapping);

要执行action

ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createAction(namespace, name, method, extraContext, true, false);

生成action代理对象

ActionContext previous = ActionContext.getContext();
ActionContext.setContext(invocation.getInvocationContext());
try{
  return invocation.invoke();
}

执行action之前,执行一系列的拦截器

执行下一个操作

return invocation.invoke();

执行该过程描述:

发送请求时候,首先到过滤器里面,在过滤器doFilter方法中执行action,首先生成action代理对象,执行,执行action之前,执行一系列默认的拦截器(把默认的拦截器拿过来),执行每一个拦截器之后做执行下一个操作,最终执行action逻辑

拦截器构成

类继承AbstractInterceptor,AbstractInterceptor类实现Interceptor接口

AbstractInterceptor implements Interceptor

在Interceptor接口里面有三个方法

void init(); //初始化操作
String intercept(ActionInvocation invocation) throw Exception;//写拦截器逻辑
void destroy();//销毁操作

自己写拦截器:

  1. 写类继承AbstractInterceptor类,重写类里面的方法Intercept方法,写拦截器逻辑
  2. 配置拦截器(注册拦截器)

几个重要概念比较

拦截器和过滤器比较

过滤器:在到达目标资源之前进行的操作,过滤器可以过滤的内容有servlet、action、jsp、图片,过滤器理论上可以过滤任何的内容/*

拦截器:在到达目标资源之前进行的操作,拦截器不能拦截jsp、图片。只能拦截action

Action和Servlet比较

Servlet:servlet默认在第一次访问时候创建,创建一次,servlet实例只有一个

Action:action在访问时候创建,创建多次,每次访问action时候都会创建action实例

自定义拦截器

需求:登录拦截器

  1. 在页面中输入用户名和密码,提交数据到action中
  2. 在action中获取用户名和密码,判断用户名和密码是否正确
  3. 如果用户名和密码正确,到主页面中
    1. 登录成功后,把用户信息放到session里面,跳转到主页面
    2. 在主页面里面,写超链接,到另一个添加的action里面
  4. 如果用户名和密码不正确,到登录页面

如果用户直接访问主页面,点击超链接到action中,如果没有登录,不能到action中页面,直接返回登录页面。

实现的基本过程步骤:

第一步 创建类,继承类

public class MyInterceptor extends AbstracrInterceptor {
  //写拦截器逻辑
  @Override
  publicc String intercept(ActionInvocation invocation) throws Exception{
    //判断是否登录
    //判断session里面是否有数据
    ActionContext context = invocation.getInvocationContext();
    Object obj = context.getSession().get("user");
    if(obj != null) {
      //登录
      return invocation.invoke();
    } else {
      //不是登录
      return Action.LOGIN;
    }
  }
}

第二步 注册拦截器

第一种方式:

声明拦截器,在要拦截的action所在的包里面

<!--声明拦截器-->
<interceptors>
    <interceptor name="myloginintercept" class="cn.xxx.MyInterceptor"></interceptor>
</interceptors>

在action标签里面使用声明的拦截器

<action name="adduser" class="com.xxx.AddUserAction">
    <result name="success">/login/add.jsp</result>
    <result name="login">/login/login.jsp</result>
    <!--如果使用自定义的拦截器,默认的拦截器失效,手动显示声明默认的拦截器-->
    <interceptor-ref name="defaultStack"></interceptor-ref>
    <!--使用自定义拦截器-->
    <interceptor-ref name="myloginintercept"></interceptor-ref>
</action>

第二种方式:

声明拦截器栈

<!--声明拦截器-->
<interceptors>
    <interceptor name="myLoginIntercept" class="com.xxx.MyInterceptor"></interceptor>
    <intercepror-stack name="loginstack">
        <!--如果使用自定义的拦截器,默认的拦截器失效,手动显示声明默认的拦截器-->
        <interceptor-ref name="defaultStack"></interceptor-ref>
        <!--使用自定义拦截器-->
        <interceptor-ref name="myLoginIntercept"></interceptor-ref>
    </intercepror-stack>
</interceptors>

在action里面直接使用声明的栈

<!--直接使用声明的栈-->
<interceptor-ref name="loginstack"></interceptor-ref>

Struts2实现文件上传

Javaweb文件上传

使用FileUpload组件,首先导入jar包

步骤:

  1. 创建磁盘文件项工厂
  2. 创建核心上传类
  3. 解析request对象
  4. 解析之后返回List<FileItem>集合
  5. 遍历list集合,判断是普通输入项,还是文件上传项
  6. 如果是文件上传项,写上传代码

Struts2里面在fileupload的基础之上做进一步封装

要求:

  1. 提交方式post
  2. form标签里面属性enctype,属性值multipart/form-data
  3. 表单里面有文件上传项,type="file",必须有name属性

实现过程

第一步 声明几个变量

​ 第一个变量是上传文件private File文件上传项里面name的值

​ 第二个变量是上传文件的名称private String文件上传里面name属性值Filename

​ 第三个变量是上传文件的mime类型

第一个变量是必须有的,但是第二个和第三个不是必须的

private File upload;
private String uploadFileName;

第二步 生成声明变量的set和get方法

public File getUpload() {
  return upload;
}
public void setUpload(File upload) {
  this.upload = upload;
}
public String getUploadFileName() {
  return uploadFileName;
}
public void setUploadFileName(String uploadFileName) {
  this.uploadFileName = uploadFileName;
}

第三步 在action的方法写上传的操作

  1. 获取到上传到服务器的文件夹路径
  2. 在服务器的文件夹中创建文件
  3. 把上传的文件内容复制到服务器上创建的文件中去
//获取服务器上面文件夹的路径
//使用servlet里面的ServletContext对象
ServletContext context = ServletActionContext.getServletContext();
String path = context.getRealPath("/img");
//在服务器的文件夹里面创建文件
File serverFile = new File(path+"/"+uploadFileName);
//把上传的文件复制到服务器文件中
FileUtils.copyFile(upload, serverFile);

上传问题解决

Struts2做上传,默认的上传的大小限制是2M,如果上传文件超过2M,返回提示信息,到页面中获取提示信息

错误提示

设置上传文件的大小,设置常量

struts.multipart.maxSize=2097152 

默认上传文件总大小是2M,常量的值是字节的单位

Struts2实现多文件上传

实现步骤

第一步

满足上传的三个要求,但是上传多个文件,在表单里面写多个文件上传项,多个文件上传项里面都有name属性,name属性值必须一样

选择文件1:<input type="file" name="uploadimg"/><br>
选择文件2:<input type="file" name="uploadimg"/><br>
选择文件3:<input type="file" name="uploadimg"/><br>
<input type="submit" value="上传"/>

第二步

声明几个变量,因为有多个值,使用数组形式声明

private File[] uploadimg;
private String[] uploadimgFileName;

第三步 生成set和get方法

public File[] getUploadimg() {
  return uploadimg;
}
public void setUpload(File[] uploadimg) {
  this.uploadimg = uploadimg;
}
public String[] getUploadimgFileName() {
  return uploadimgFileName;
}
public void setUploadimgFileName(String[] uploadimgFileName) {
  this.uploadimgFileName = uploadimgFileName;
}

第三步 在action方法中实现上传的操作

变量数组,得到每一个文件的信息,一个一个的上传到服务器中

//遍历得到每一个文件内容,一个个上传到服务器中
for(int i = 0; i < uploadimgFileName; i++) {
  File uploadFile = uploadimg[i];
  String filename = uploadimgFileName[i];
  //实现上传
  String path = ServletActionContext.getServletContext().gerRealPath("/img");
  File serverFile = new File(path+"/"+filename);
  FileUtils.copyFile(uploadFile, serverFile);
} 

Struts2实现文件下载

Javaweb实现文件下载

第一步:获取服务器上的文件

第二步:把文件通过流的方式写到浏览器中

设置头 Content-Disposition,无论什么格式都是下载,而不是直接打开

实现过程

首先 在配置文件中配置下载的信息

<package name="downloaddemo" extends="struts-default" namespace="/">
    <action name="down" class="com.xx.DownloadAction">
        <result name="success" type="stream">
            <param name="contentDisposition">attachment;filename=${filename}</param>
            <param name="inputStream">${inputStream}</param>
        </result>
    </action>
</package>

配置contentDisposition和inputStream

这两个值通过action传递过来

第二步 在action提供这个值的get方法

//提供fileName的get方法
String filename = "2.jpg";
public String getFileName() {
  return filename;
}
public InputStream getInputStream() throws FileNotFoundException() {
  String path = ServlerActionContext.getServletContext().getRealPath("/img/"+filename);
  InputStream in = new FileInputStream(path);
  return in;
}

Struts下载中文名称文件乱码

不同的浏览器有不同的编码,ie采用url编码,火狐采用base64编码

首先,区分不同的浏览器

Request对象,有方法getHeader(),使用头获取浏览器类型,头信息 User-Agent

Request.getHeader(“User-Agent”);

判断不同的浏览器,做不同编码

如果是火狐,使用base64编码

如果是ie及其他浏览器,使用url编码

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

推荐阅读更多精彩内容