struts2学习笔记 总结1

配置文件

一、struts.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
   <!--package中
        name:package的名称,用来多个package的区分 
        namespace:命名空间 默认为/ ,如果namespace="/e",则访问路径为localhost/HelloAction/e/hello
        extends:属性固定值,默认struts-default
     -->
 
<package name="demo" extends="struts-default" namespace="/">
   
        <!--action中 
            method默认执行execute方法
             class =包+.类名
              通过name访问
         -->

        <action name="hello" class="com.lx.demo.helloAction" method="">

            <!--    
                result中
                name与method指定方法的返回值一致
                默认的name值是“success
                type:配置如何到另外一个路径中去(转发或者重定向)默认为转发 
            -->

            <result name="ok">/index.jsp</result>   
        </action>
</package>

<package name="demo2" extends="struts-default" namespace="/e">
    <action name="login" class="com.lx.demo.helloAction" method="login">
        <result name="log">/test.jsp</result>
    </action>
</package>

<!--覆盖系统默认常量(libraties下struts2-core-2.5.20.jar包里面的
    org.apache.struts2里的default,properties)  -->

<constant name="struts.i18n.encoding " value="GBk"></constant>
</struts>
  1. <package>标签,如果要配置<Action>的标签,那么必须要先配置<package>标签,代表的包的概念
  • 包含的属性
    • name -- 包的名称,要求是唯一的,管理action配置
    • extends -- 继承,可以继承其他的包,只要继承了,那么该包就包含了其他包的功能,一般都是继承struts-default
    • namespace -- 名称空间,一般与<action>标签中的name属性共同决定访问路径(通俗话:怎么来访问action),常见的配置如下
      • namespace="/" -- 根名称空间
      • namespace="/aaa" -- 带有名称的名称空间
    • abstract -- 抽象的。这个属性基本很少使用,值如果是true,那么编写的包是被继承的
  1. <action>标签
  • 代表配置action类,包含的属性
    • name -- 和<package>标签的namespace属性一起来决定访问路径的
    • class -- 配置Action类的全路径(默认值是ActionSupport类)
    • method -- Action类中执行的方法,如果不指定,默认值是execute
  1. <result>标签
  • action类中方法执行,返回的结果跳转的页面
    • name -- 结果页面逻辑视图名称
    • type -- 结果类型(默认值是转发,也可以设置其他的值)

二、模块化struts.xml文件的方法

  • 文件拆分为多个xml文件,并用以下方式导入它们
<struts>
    <include file="com/lx/frist/test/struts-pay.xml"></include>
    <include file="com/lx/second/test/struts-user.xml"></include>
</struts>

三、通配符实现

访问时用http://localhost/HelloAction/p/user_add

<package name="Pay" extends="struts-default" namespace="/p">
    <action name="user_*" class="com.lx.frist.test.PayAction" method="{1}" >
        <result name="add">/index.jsp</result>
        <result name="delete">/index.jsp</result>
        <allowed-methods>add,delete</allowed-methods>
    </action>
</package>

四、注意

配置xml文件时需要极其非常一定要注意的点:

  1. <package>标签的namespace在访问时需要用到,很重要
  1. <action>标签的method方法默认执行execute方法 </br>如果表单要提交的方法不是execute,而是其他方法,如:在<form>标签里配置的action是login.action,
    <form action="<%=request.getContextPath() %>/login.action ">而xml里name为login的这个action没有给method赋值,此时将会出现404There is no Action mapped for namespace [/u] and action name [login] associated with context path [/HelloAction].也就是说如果需要该action执行的方法不是execute方法,那么一定要将真正需要执行的方法名赋值给method
  2. 用通配符访问需要注意向Action类里面添加方法或者修改方法名后,一定要<allowed-methods>标签里添加该方法,不然又会出现404

Action

自定义Action一般继承ActionSupport类

  • Action访问Servlet-API
  1. 让Action类实现对应aweargan感知接口ServletRequestAwear,ServletresponseAwear,SessionAwear分别获取

      public class TestAction implements ServletRequestAware,ServletResponseAware {
      private HttpServletRequest request;
      private HttpServletResponse response;
      @Override
      public void setServletResponse(HttpServletResponse response) {
      this.response=response;
      }
      
      @Override
      public void setServletRequest(HttpServletRequest request) {
      this.request=request;
      }   
    

    }

  2. 通过ServletActionContext工具类

     public class TestAction {
     public String getObject() {
         HttpServletRequest request = ServletActionContext.getRequest();
         HttpServletResponse response = ServletActionContext.getResponse();
         HttpSession session = ServletActionContext.getRequest().getSession();
         return null;
         }
     }
    
  3. 通过ActionContext类
    获取Action的上下文对象ActionContext.getContext(),在ActionContext中把request,session,application三大作用域对象作为Map对象,通过Map对象即可获取

     import java.util.Map;
     
     import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpServletResponse;
     
     import com.opensymphony.xwork2.ActionContext;
    
     public class TestAction {
    
         public String getObject() {
             // ActionContext context = ActionContext.getContext();
          // Map request = (Map)context.get("request");
          // Map session = context.getSession();
             HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(org.apache.struts2.StrutsStatics.HTTP_REQUEST);
             HttpServletResponse response = (HttpServletResponse) ActionContext.getContext().get(org.apache.struts2.StrutsStatics.HTTP_RESPONSE);
             Map<String, Object> session = ActionContext.getContext().getSession();
             session.put("USER-INFO", userName);//在session中保存
             return NONE;
         }
     }
    

拦截器

拦截器实现以下操作:

  • 在调用action之前提供预处理逻辑。
  • 在调用action后提供后处理逻辑。
  • 捕获异常,以便可以执行备用处理。

一、自定义拦截器

  1. 实现com.opensyphony.xwork.interceptor.interceptor
  2. 继承com.opensyphony.xwork.interceptor.AbstractInterceptor
  3. 根据具体需要重写intercepter方法
  4. 在struts.xml中注册拦截器
  5. 如果某个Action有制定拦截器,默认拦截器将无效
    方式一:
<interceptors>
   <interceptor name="DemoInterceptor" class="com.itheima.interceptor.DemoInterceptor"/>
</interceptors>

<action name="userAction" class="com.itheima.demo3.UserAction">
   <!-- 只要是引用自己的拦截器,默认栈的拦截器就不执行了,必须要手动引入默认栈 -->
   <interceptor-ref name="DemoInterceptor"/>
   <interceptor-ref name="defaultStack"/>
</action>

方式二:

<interceptors>
    <interceptor name="DemoInterceptor" class="com.itheima.interceptor.DemoInterceptor"/>
    <!-- 定义拦截器栈 -->
    <interceptor-stack name="myStack">
        <interceptor-ref name="DemoInterceptor"/>
        <interceptor-ref name="defaultStack"/>
    </interceptor-stack>
</interceptors>

<action name="userAction" class="com.itheima.demo3.UserAction">
    
    <!-- 引入拦截器栈 -->
    <interceptor-ref name="myStack"/>
</action>

思考1:如果package有100个action,其中98个需要用到某个拦截器,怎么办?
可以将该拦截器和默认拦截器栈添加到自己定义的拦截器栈(方法二),并且定义为默认拦截器栈<default-interceptor-ref name = "myStack">

思考2:按照上述解决方法,那剩余两个不用该拦截器却使用了该拦截器,这个时候怎么办?
给这两个单独加自己的拦截器,这样会覆盖之前定义的默认拦截器栈myStack,一般误其他要求引入defaultStack就好,也就是加上这行代码
<interceptor-ref name = "defaultStack" />

二、方法拦截器

  • 拦截器继承MethodFilterInterceptor
  • 细化到拦截某个方法,而不是某个Action
  • 指定需拦截或无需拦截的方法,在<interceptor-ref>标签里加入代码
  1. <param name = "excludeMethods">方法名</param>
    多个方法用逗号隔开,指明拦截器不要拦截的方法
  2. <param name = "includeMethods">方法名</param>
    指明所要拦截的方法
    注意:includeMethod优先于excludeMethod

ONGL、值栈、标签库

前提:<%@ taglib prefix="s" uri="/struts-tags" %>

ONGL\标签库

https://blog.csdn.net/shaonianbz/article/details/79145925

值栈

https://blog.csdn.net/shaonianbz/article/details/79183725


文件上传,下载

一、文件上传

  1. 文件上传配置
  • 文件上传条件:
    (1)用post方式
    (2)使用二进制编码:multipart/form-data
    (3)<input type="file" name="***" />

    <form action="upload" method="post" enctype="multipart/form-data">
          <label for="myFile">Upload your file</label>
          <input type="file" name="myFile" />
          <input type="submit" value="Upload"/>
      </form>
    
  • 上传文件默认为2M,可以通过修改常量设置,如:<constant name="struts.multipart.maxSize" value="1000000" />

  • 如果只想对当前form表单有效,可以设置fileUpload拦截器属性

     <action name="upload" class="cn.w3cschool.struts2.uploadFile">
        <interceptor-ref name="basicStack">
        <interceptor-ref name="fileUpload">
             <param name="maximumSize">20971520</param><!-- 文件最大20m -->
             <param name="allowedTypes">image/jpeg,image/gif</param>
         <!--设置上传文件允许的后缀名,多个使用逗号隔开  -->
               <param name="allowedExtensions"></param>
        </interceptor-ref>
        <result name="success">/success.jsp</result>
        <result name="error">/error.jsp</result>
      </action>
    

还可以设置上传文件允许的后缀名,多个使用逗号隔开如: <param name="allowedExtensions">txt,avi</param>

  • 关于限制文件大小,如果限制的最大值超过2M则需要在struts.xml中增加<constant name="struts.multipart.maxSize" value="21000000"/>,这行代码表示整个项目所有要上传文件的地方允许上传的文件大小的最大值,也就是说这个项目里上传的任何单个文件大小不能超过21000000字节(约20M),如果项目中不添加这行代码,则默认允许上传的文件大小最大为2M,
  • 超过文件总大小时,跳转Input,

2 . action类代码需要注意的是:
(1)上传文件名命名规则:上传的字段名(form表单中的input的name)+FileName
(2)MIME类型命名规则:上传的字段名(form表单中的input的name)+ContentType
(3)表单中提供的属性和struts提供的属性需要set,get方法
(4)注意需要导入包,如下

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class PayAction extends ActionSupport {

private File myFile;
private String myFileFileName;
private String myFileNameContentType;

@Override
public String execute() {
    System.out.println("进入pay");
    return SUCCESS;
}

public String addd() {
    System.out.println("add");
    return "add";
}

public String delete() {
    System.out.println("delete");
    return "delete";        
}

 public String upload(){
        //获取项目部署到的磁盘绝对路径
        String realPath = ServletActionContext.getServletContext().getRealPath("/");
        System.out.println(realPath+"dahfo");
        //指定目录创建文件
        File destFile = new File(realPath, myFileFileName);
        //复制到指定目录的文件
        try {
            FileUtils.copyFile(myFile,destFile);
            myFile.delete();
            
        } catch (IOException e) {
            e.printStackTrace();
            return "fail";
        }
      
        return "ok";
}
 
 public File getMyFile() {
        return myFile;
    }

    public void setMyFile(File myFile) {
        this.myFile = myFile;
    }

    public String getMyFileFileName() {
        return myFileFileName;
    }

    public void setMyFileFileName(String myFileFileName) {
        this.myFileFileName = myFileFileName;
    }

    public String getMyFileNameContentType() {
        return myFileNameContentType;
    }

    public void setMyFileNameContentType(String myFileNameContentType) {
        this.myFileNameContentType = myFileNameContentType;
    }
}

二、文件下载

  • xml配置
<package name="p2" extends="struts-default"> 
    <action name="download" class="com.san.action.Download" method="download">
         <!--stream类型:直接向页面输出二进制数据 --> 
        <result name="ok" type="stream">
         <!-- 给stream结果视图注入参数:Content-Type -->
         <param name="contentType">application/octet-stream</param>
         <!-- 告知浏览器一什么方式打开 ${@java.net.URLEncoder@encode(fileName,"UTF-8")}--> 
        <param name="contentDisposition">attachment;fileName=1.jpg</param> 
        <!-- 注入字节流,取值要写动作类中的set方法名称,首字母改成小写 --> 
        <param name="inputName">inputStream</param> </result>
     </action> 
</package>
  • action核心代码
public String download() throws Exception{ 
    //1、找到文件存储位置 
    String filePath=ServletActionContext.getServletContext().getRealPath("/WEB-INF/download/file1.txt"); 
    
    file = new File(filepath,fileName);
    //2、把文件读入到InputStream流中 
    inputStream=new FileInputStream(file);  
    return "ok"; 
    }
 public InputStream getInputStream() {
     return inputStream; 
    }
  • jsp文件,开头引入标签库<%@ taglib prefix="s" uri="/struts-tags" %>

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