Struts2基础知识(二)

本文主要包括以下内容

  1. 文件上传,多文件上传
  2. 自定义拦截器
  3. 用户输入验证
  4. 国际化

文件上传

这里写图片描述

这里写图片描述

  • 将头设置为enctype=”multipart/form-data”
 <body>
    <form action="${pageContext.request.contextPath}/upload/upload1.action" method="post" enctype="multipart/form-data">
        文件:<input type="file" name="image"/><br/>
        <input type="submit" value="上传"/>
    </form>
  </body>
  • 写接收处理的方法,有两种,一种是自己实现IO流,一种是使用FileUtils
package cn.itcast.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;

import javax.servlet.ServletContext;

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

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class UploadAction1 extends ActionSupport implements Serializable {

    private File image;//对应的就是表单中文件上传的那个输入域的名称,Struts2框架会封装成File类型的
    private String imageFileName;//   上传输入域FileName  文件名
    private String imageContentType;// 上传文件的MIME类型

    public File getImage() {
        return image;
    }



    public void setImage(File image) {
        this.image = image;
    }



    public String getImageFileName() {
        return imageFileName;
    }



    public void setImageFileName(String imageFileName) {
        this.imageFileName = imageFileName;
    }



    public String getImageContentType() {
        return imageContentType;
    }



    public void setImageContentType(String imageContentType) {
        this.imageContentType = imageContentType;
    }



    public String execute(){
        System.out.println(imageContentType);
        try {
            //处理实际的上传代码
            //找到存储文件的真实路径
        System.out.println(imageFileName);
            ServletContext sc = ServletActionContext.getServletContext();
            String storePath = sc.getRealPath("/files");
            //构建输入输出流
            /*OutputStream out = new FileOutputStream(storePath+"\"+imageFileName);
            InputStream in = new FileInputStream(image);
            byte b[] = new byte[1024];
            int len = -1;
            while((len=in.read(b))!=-1){
                out.write(b, 0, len);
            }
            out.close();
        in.close();*/

        FileUtils.copyFile(image, new File(storePath,imageFileName));

            ActionContext.getContext().put("message", "上传成功!");
            return SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            return ERROR;
        }
    }
}

多文件上传实现

package cn.itcast.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;

import javax.servlet.ServletContext;

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

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class UploadAction2 extends ActionSupport implements Serializable {

    private File[] images;//对应的就是表单中文件上传的那个输入域的名称,Struts2框架会封装成File类型的
    private String[] imagesFileName;//   上传输入域FileName  文件名
    private String[] imagesContentType;// 上传文件的MIME类型



    public File[] getImages() {
        return images;
    }



    public void setImages(File[] images) {
        this.images = images;
    }



    public String[] getImagesFileName() {
        return imagesFileName;
    }



    public void setImagesFileName(String[] imagesFileName) {
        this.imagesFileName = imagesFileName;
    }



    public String[] getImagesContentType() {
        return imagesContentType;
    }



    public void setImagesContentType(String[] imagesContentType) {
        this.imagesContentType = imagesContentType;
    }



    public String execute(){
        try {

            if(images!=null&&images.length>0){
                ServletContext sc = ServletActionContext.getServletContext();
                String storePath = sc.getRealPath("/files");
                for(int i=0;i<images.length;i++)
                    FileUtils.copyFile(images[i], new File(storePath,imagesFileName[i]));
            }
            ActionContext.getContext().put("message", "上传成功!");
            return SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            return ERROR;
        }
    }
}

自定义拦截器

这里写图片描述

这里写图片描述

1、编写一个类,实现 com.opensymphony.xwork2.interceptor.Interceptor

2、主要实现public String intercept(ActionInvocation invocation) throws Exception{}方法

        该方法的返回值就相当于动作的返回值
        如果调用了String result = invocation.invoke();得到了动作类的返回的值。
    public String intercept(ActionInvocation invocation) throws Exception {
        //判断用户是否登录
        HttpSession session = ServletActionContext.getRequest().getSession();
        Object obj = session.getAttribute("user");
        if(obj==null){
            return "login";
        }else{
            return invocation.invoke();//调用动作方法
        }
    }

3、拦截器定义好后,一定要在配置文件中进行注册:

        <interceptors> 只是定义拦截器,并没有起作用 
            <interceptor name="permissionInterceptor" class="cn.itcast.interceptor.PermissionInterceptor"></interceptor>
        </interceptors>

4、配置文件中的动作,要通过

        <interceptor-ref name="permissionInterceptor"></interceptor-ref>使用该拦截器

注意:一旦动作中使用了自定义的拦截器,那么默认的就不起作用了。一般应该采用如下的做法:

        <interceptor-ref name="defaultStack"></interceptor-ref>
        <interceptor-ref name="permissionInterceptor"></interceptor-ref>

多个动作类都要使用的话,可以通过package来进行组合。

<package name="mypackage" extends="struts-default">
        <interceptors> <!--  只是定义拦截器,并没有起作用 -->
            <interceptor name="permissionInterceptor" class="cn.itcast.interceptor.PermissionInterceptor"></interceptor>
            <interceptor-stack name="mydefaultstack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="permissionInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 配置全局错误结果 :范围只是本包-->
        <global-results>
            <result type="dispatcher" name="error">/customer/error.jsp</result>
        </global-results>

    </package>

<package name="interceptor" extends="mypackage">
        <action name="visitIndex" class="cn.itcast.action.VisitAction" method="execute">
            <interceptor-ref name="mydefaultstack"></interceptor-ref>

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

用户输入验证

1、编程方式:

动作类中的所有方法进行验证:
            步骤:
            a、动作类继承ActionSupport
            b、覆盖调用public void validate()方法
            c、在validate方法中,编写不符合要求的代码判断,并调用父类的addFieldError(String fieldName,String errorMessage)
                如果fieldError(存放错误信息的Map)有任何的元素,就是验证不通过,动作方法不会执行。
                Struts2框架会返回到name=input的result
            d、在name=input指定的页面上使用struts2的标签显示错误信息。<s:fielderror/>

        动作类中指定的方法进行验证:
            编写步骤与上面相同

            验证方法书写有要求:
                public void validateXxx()   Xxx代表的是要验证的动作方法名,其中要把动作方法名的首字母变为大写。

2、基于XML配置文件的方式:

动作类中的所有方法进行验证:
            在动作类的包中,建立一个名称为:动作简单类名-validation.xml ,比如要验证的动作类名是UserAction   UserAction-validation.xml
            内容如下:
            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE validators PUBLIC
                    "-//OpenSymphony Group//XWork Validator 1.0.3//EN"
                    "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
            <validators>
                <field name="username">
                    <!-- 内置验证器都是定义好的,在xwork-core.jar com.opensymphony.xwork2.validator.validators包中的default.xml文件中 -->
                    <field-validator type="requiredstring"><!-- 不能为null或者""字符串,默认会去掉前后的空格 -->
                        <message>用户名不能为空</message>
                    </field-validator>
                </field>
            </validators>
        动作类中指定的方法进行验证:
            配置文件的名称书写有一定要求。
                    动作类名-动作名(配置文件中的动作名)-validation.xml
                    UserAction-user_add-validation.xml

3、自定义基于XML的验证器

a、编写一个类,继承FieldValidatorSupport类。
        b、在public void validate(Object object)编写你的验证逻辑
                不符合要求的就向fieldErrors中放消息
        c、一定注册你的验证器才能使用
                在WEB-INF/classes目录下建立一个名称为validators.xml的配置文件,内容如下:
                <validators>
                    <validator name="strongpassword" class="cn.itcast.validators.StrongPasswordValidator"/>
                </validators>
        d、日后就可以像使用Struts2提供的16个验证器方式去使用了。

实例

package cn.itcast.validators;

import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;

public class StrongPasswordValidator extends FieldValidatorSupport {

    public void validate(Object object) throws ValidationException {
        String fieldName = getFieldName();//取得字段名
        String filedValue = (String)getFieldValue(fieldName, object);//取得用户输入的当前字段的值
        if(!isPasswordStrong(filedValue)){
            addFieldError(fieldName, object);
        }
    }
    private static final String GROUP1 = "abcdefghijklmnopqrstuvwxyz";
    private static final String GROUP2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String GROUP3 = "0123456789";
    protected boolean isPasswordStrong(String password) {
        boolean ok1 = false;
        boolean ok2 = false;
        boolean ok3 = false;
        int length = password.length();
        for(int i=0;i<length;i++){
            if(ok1&&ok2&&ok3)
                break;
            String character = password.substring(i,i+1);
            if(GROUP1.contains(character)){
                ok1 = true;
                continue;
            }
            if(GROUP2.contains(character)){
                ok2 = true;
                continue;
            }
            if(GROUP3.contains(character)){
                ok3 = true;
                continue;
            }
        }
        return ok1&&ok2&&ok3;
    }
}

Struts2对于i18n的支持

全局资源文件/包范围资源文件/动作类的资源文件
    全局资源文件:放到WEB-INF/classes目录下
    包范围资源文件:服务于Java类中的包下的动作类的。  

            取名:package_语言_国家.properties

    动作类的资源文件:放到与动作类相同的包中
            取名:动作类名_语言_国家.properties

jsp中如何读取国际化的消息

<body>
    <s:i18n name="itcast">
        <s:text name="welcome">
            <s:param>yr</s:param>
            <s:param>study</s:param>
        </s:text>
    </s:i18n>
    <s:i18n name="cn/itcast/action/package">
        <s:text name="welcome">
            <s:param>wxy</s:param>
            <s:param>find boy friend</s:param>
        </s:text>
    </s:i18n>
  </body>

动作类中如何读取国际化的消息

public class I18nAction extends ActionSupport implements Serializable {
    public String execute(){
        //取出资源文件中的welcome的值
//      String value = getText("welcome");
        String value = getText("welcome", new String[]{"朱巧玲","学习"});
        //封装到请求范围中
        ActionContext.getContext().put("message", value);
        return SUCCESS;
    }
}

完成

原文地址:https://www.cnblogs.com/jjx2013/p/6223688.html