From: Polin Wei

經實作測試,可以正常運作。故記錄之.....

環境:

struts2: 2.3.16.3

freemarker: 2.3.19

Bootstrap: 3.2.0

commons-fileupload: 1.3.1

commons-io:2.4

jQuery-File-Upload: 9.10.0

 

上傳前劃面

 upload-1.png  

上傳後劃面

upload2.png

 

Struts2 結合 jQuery-File-Upload 的實作如下:

step 01: pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.gu</groupId>
  <artifactId>GUSSH</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <name>gussh</name>
  <dependencies>
          <dependency>
              <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
          </dependency>
          <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>4.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.1.1.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.2.15.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.2.15.Final</version>
        </dependency>
        
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.3</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-core</artifactId>
            <version>2.3.16.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-spring-plugin</artifactId>
            <version>2.3.16.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-json-plugin</artifactId>
            <version>2.3.16.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-config-browser-plugin</artifactId>
            <version>2.3.16.3</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.8.0</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>commons-digester</groupId>
            <artifactId>commons-digester</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>p6spy</groupId>
            <artifactId>p6spy</artifactId>
            <version>1.3</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.0.1-FINAL</version>
        </dependency>
        <dependency>
            <groupId>quartz</groupId>
            <artifactId>quartz</artifactId>
            <version>1.5.2</version>
        </dependency>
        
        <dependency>
            <groupId>stax</groupId>
            <artifactId>stax</artifactId>
            <version>1.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml</groupId>
            <artifactId>saaj-impl</artifactId>
            <version>1.3</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.stream</groupId>
            <artifactId>sjsxp</artifactId>
            <version>1.0.1</version>
        </dependency>
        
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
            <version>1.5.1</version>
        </dependency>
        <dependency>
            <groupId>oro</groupId>
            <artifactId>oro</artifactId>
            <version>2.0.8</version>
        </dependency>
        <dependency>
            <groupId>jasperreports</groupId>
            <artifactId>jasperreports</artifactId>
            <version>1.3.4</version>
        </dependency>
        <dependency>
            <groupId>jfree</groupId>
            <artifactId>jfreechart</artifactId>
            <version>1.0.9</version>
        </dependency>
        <dependency>
            <groupId>jfree</groupId>
            <artifactId>jfreechart-experimental</artifactId>
            <version>1.0.9</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <classifier>jdk15</classifier>
        </dependency>
        
        <dependency>
            <groupId>net.sf.barcode4j</groupId>
            <artifactId>barcode4j</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>net.sf.morph</groupId>
            <artifactId>morph</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils-bean-collections</artifactId>
            <version>1.7.0</version>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.5.3</version>
        </dependency>
        <dependency>
            <groupId>axis</groupId>
            <artifactId>axis</artifactId>
            <version>1.4</version>
        </dependency>
        
        <dependency>
            <groupId>com.keypoint</groupId>
            <artifactId>png-encoder</artifactId>
            <version>1.5</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.2.2</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>2.1_3</version>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>jsr250-api</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>1.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.transaction</groupId>
            <artifactId>jta</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>1.5.2</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.jexcelapi</groupId>
            <artifactId>jxl</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>commons-javaflow</groupId>
            <artifactId>commons-javaflow</artifactId>
            <version>20060411</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/commons-javaflow-20060411.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>net.sourceforge.barbecue</groupId>
            <artifactId>barbecue</artifactId>
            <version>1.1</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/barbecue-1.1.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>lotus.sametime</groupId>
            <artifactId>STComm</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/STComm.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>lotus.sametime</groupId>
            <artifactId>NCSO</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/NCSO.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>lotus.sametime</groupId>
            <artifactId>CommRes</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/CommRes.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>com.wnjsoft.dlp</groupId>
            <artifactId>ds-orgimport</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/ds-orgimport.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>com.wnjsoft.dlp</groupId>
            <artifactId>ds-userimport</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/ds-userimport.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>com.ds.globeunion.wfclient</groupId>
            <artifactId>ds-wf-client</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/ds-wf-client.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>jasperreports</groupId>
            <artifactId>ireport</artifactId>
            <version>2.0.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/iReport.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc14</artifactId>
            <version>10.2.0.3.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/ojdbc14.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc14_g</artifactId>
            <version>10.2.0.3.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/ojdbc14_g.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>com.sun.xml</groupId>
            <artifactId>saaj-coms</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/saaj-coms.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>com.gu.apps</groupId>
            <artifactId>gu-taglibs</artifactId>
            <version>1.0.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/gu-taglibs-1.0.0.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>javax.sql</groupId>
            <artifactId>jdbc-stdext</artifactId>
            <version>2.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/jdbc2_0-stdext.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>com.jgeppert.struts2.bootstrap</groupId>
            <artifactId>struts2-bootstrap-plugin</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.jgeppert.struts2.jquery</groupId>
            <artifactId>struts2-jquery-plugin</artifactId>
            <version>3.7.1</version>
        </dependency>
        <dependency>
            <groupId>com.ckeditor</groupId>
            <artifactId>ckeditor-java-core</artifactId>
            <version>3.5.3</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
  </dependencies>
</project>

 

step 02: struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
      
<struts>

     <!-- devMode is helpful when you want some extra logs for debugging -->
     <constant name="struts.devMode" value="false" />
     <constant name="struts.i18n.encoding" value="UTF-8" />
     <!-- Global message resource;
         Otherwise you will have seperate message resource for each Action
     -->
     <constant name="struts.custom.i18n.resources" value="com.gussh.sc.messages.messages" />
     <constant name="struts.enable.DynamicMethodInvocation" value="true" />
     <constant name="struts.multipart.maxSize" value="1048576000" />
             
     <package name="gussh-default" namespace="/" extends="struts-default,json-default">
     
       <interceptors>
            <interceptor name="authInterceptor" class="com.gussh.AuthInterceptor"></interceptor>
            
               <interceptor-stack name="gussh-stack">
                <interceptor-ref name="fileUpload">
                    <param name="maximumSize">104857600</param>
                </interceptor-ref>
                <interceptor-ref name="authInterceptor" />                    
                <interceptor-ref name="defaultStack"/>
               </interceptor-stack> 
               
       </interceptors>
       <default-interceptor-ref name="gussh-stack"/>
       <default-action-ref name="UnderConstruction"/>
                       
       <global-results>
          <result name="json-output">/gussh/common/json-output.jsp</result>
          <result name="error">/error.jsp</result>
        </global-results>
         
        <global-exception-mappings>
            <exception-mapping exception="java.lang.Exception" result="error"/>            
        </global-exception-mappings>
        
       <action name="UnderConstruction">
           <result>/templates/SSO/GUSSO.jsp</result>
       </action>        
 
        <action name="FileOutput" class="com.gussh.common.utils.FileOutput" >              
            <result name="success" type="stream">
                <param name="contentType">application/octet-stream;charset=ISO8859-1</param>
                <param name="inputName">inputStream</param>
                <!-- 使用經過轉碼的檔名作為下載檔案名,downloadFileName屬性  對應action類中的方法 getDownloadFileName() -->  
                <param name="contentDisposition">attachment;filename="${downloadFileName}"</param>
                <param name="bufferSize">4096</param>                
            </result>  
        </action>        
            
     </package>
    
     <!-- Add addition packages and configuration here. -->
      
</struts>

 

Step03: jsp 頁面

<s:form cssClass="fileupload" name="UsersTagAction" action="UsersTagAction" enctype="multipart/form-data">

...

...

<div class="row fileupload-buttonbar">
    <div class="col-lg-7">
        <!-- The fileinput-button span is used to style the file input field as button -->
        <span class="btn btn-success btn-sm fileinput-button">
            <i class="glyphicon glyphicon-plus" style="font-size: 14px"></i>
            <span><s:text name="common.upload.select" /></span>
            <input type="file" name="file" multiple>                    
        </span>           
        <button type="submit" class="btn btn-primary btn-sm start">
            <i class="glyphicon glyphicon-upload" style="font-size: 14px"></i>
            <span><s:text name="common.upload" /></span>
        </button>
        <button type="reset" class="btn btn-warning btn-sm cancel">
            <i class="glyphicon glyphicon-ban-circle" style="font-size: 14px"></i>
            <span><s:text name="common.upload.cancel" /></span>
        </button>
        <button type="button" class="btn btn-danger btn-sm delete">
            <i class="glyphicon glyphicon-trash" style="font-size: 14px"></i>
            <span><s:text name="common.btn.delete" /></span>
        </button>
        <input type="checkbox" class="toggle">
        <!-- The global file processing state -->
        <span class="fileupload-process"></span>
    </div>
</div>
<!-- The table listing the files available for upload/download -->
<table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>

 

...</s:form>

 

step 04: freemarker(ftl) 頁面, 放在 html 最下面, 以便所有頁面共用

<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
    <tr class="template-upload fade">
        <td>
            <span class="preview"></span>
        </td>
        <td>
            <p class="name">{%=file.name%}</p>
            <strong class="error text-danger"></strong>
        </td>
        <td class="title"><input name="fileDescription" placeholder="File Description"></td>    
        <td>
            <p class="size">Processing...</p>
            <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>
        </td>
        <td>
            {% if (!i && !o.options.autoUpload) { %}
                <button class="btn btn-primary btn-sm start" disabled>
                    <i class="glyphicon glyphicon-upload" style="font-size: 14px"></i>
                    <span style="font-size: 12px">${action.getText('common.upload.select')}</span>
                </button>
            {% } %}
            {% if (!i) { %}
                <button class="btn btn-warning btn-sm cancel">
                    <i class="glyphicon glyphicon-ban-circle" style="font-size: 14px"></i>
                    <span style="font-size: 12px">${action.getText('common.upload.cancel')}</span>
                </button>
            {% } %}
        </td>
    </tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
    <tr class="template-download fade">
        <td>
            <span class="preview">
                {% if (file.thumbnailUrl) { %}
                    <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
                {% } %}
            </span>
        </td>
        <td>
            <p class="name">                
                {% if (file.url) { %}
                    <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}><img src="${request.contextPath}/webTemplate/themes/gussh/images/Download-icon.png"/>{%=file.name%}</a>
                {% } else { %}
                    <span>{%=file.name%}</span>
                {% } %}
            </p>
            {% if (file.error) { %}
                <div><span class="label label-danger">Error</span> {%=file.error%}</div>
            {% } %}
        </td>
        <td>
            <span class="size">{%=o.formatFileSize(file.size)%}</span>
        </td>
        <td>
            {% if (file.deleteUrl) { %}
                <button class="btn btn-danger btn-sm delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
                    <i class="glyphicon glyphicon-trash" style="font-size: 12px"></i>
                    <span>${action.getText('common.btn.delete')}</span>
                </button>
                <input type="checkbox" name="delete" value="1" class="toggle">
            {% } else { %}
                <button class="btn btn-warning btn-sm cancel">
                    <i class="glyphicon glyphicon-ban-circle" style="font-size: 12px"></i>
                    <span>${action.getText('common.upload.cancel')}</span>
                </button>
            {% } %}
        </td>
    </tr>
{% } %}
</script>
    
</body>
</html>

 

Step 05: 處理 file upload 的 class

package com.gussh;


import java.lang.reflect.Method;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.mapper.ActionMapping;

import com.gussh.common.utils.BA_TOOLS;
import com.gussh.common.utils.BA_Validate;
import com.gussh.sc.model.UserInfo;
import com.gussh.spfs.SPFS_TOOLS;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
import com.opensymphony.xwork2.validator.annotations.DateRangeFieldValidator;
import com.opensymphony.xwork2.validator.validators.EmailValidator;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class BaseSupport extends ActionSupport implements Preparable {
    
    Logger logger = Logger.getLogger(BaseSupport.class);
    private static final long serialVersionUID = 1L;
    
    // 網頁會使用的 request, response, session
    public HttpServletRequest request = ServletActionContext.getRequest();
    public HttpServletResponse response = ServletActionContext.getResponse();
    public Map<String, Object> session = ActionContext.getContext().getSession();


    //處理檔案上傳, 因 jQuery-File-Upload 一次處理一個檔案上傳, 所以不需使用 MultipleFileUploadUsingListAction
    protected File file ;
    protected String fileFileName ;
    protected String fileContentType ;
    protected String fileDescription ;
    
    @Resource(name="BA_TOOLS")
    protected BA_TOOLS baTools;    
    
    public BaseSupport() {
        // TODO Auto-generated constructor stub
    }

    public void prepare() throws Exception {
        // TODO Auto-generated constructor stub
        
    }    


    @Override
    public String execute() throws Exception {
        String reqCode="fileUpload";
            String reqResult="";
            reqResult=doReqCode(reqCode);        
        return reqResult;
    }

    public String fileUpload() {
        String filePath="/upload/";
        try {
            baTools.uploadFileToServer(response, filePath, file, fileFileName, fileContentType, fileDescription);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return super.fileUpload();
    }


    //執行其它自定的 reqCode Function
    public String doReqCode(String reqCode) {
        reqResult=INPUT;
        boolean result = false;
        Method[] methods = this.getClass().getMethods();
        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            if (reqCode.equals(method.getName())) {
                try {
                    reqResult=method.invoke(this).toString();
                    result=true;
                } catch (Exception e) {
                    this.addActionError(reqCode+": "+  getText("msg.system.methodExecuteError"));
                    logger.info(e);                
                }
            }
        }
        if (!result){
            this.addActionError(reqCode+": "+  getText("msg.system.methodNotFound"));
        }
        
        return reqResult;
    }


    //處理檔案上傳
    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
    }

    public String getFileFileName() {
        return fileFileName;
    }

    public void setFileFileName(String fileFileName) {
        this.fileFileName = fileFileName;
    }

    public String getFileContentType() {
        return fileContentType;
    }

    public void setFileContentType(String fileContentType) {
        this.fileContentType = fileContentType;
    }

    public String getFileDescription() {
        return fileDescription;
    }

    public void setFileDescription(String fileDescription) {
        this.fileDescription = fileDescription;
    }
    
}

 

Step 06: 公共程式的 class: BA_TOOLS

@Service
@Component("BA_TOOLS")
public class BA_TOOLS extends BaseDataSource {

    static Logger loger = Logger.getLogger(BA_TOOLS.class.getName());
    
    private static final ActionSupport actionSupport = new ActionSupport();
    
    /**
     * 上傳檔案到主機上,並且變更原始檔名為 new Date().getTime() + extension
     * @param filePath 檔案路徑
     * @param file     上傳的實體檔案來源
     * @param fileFileName 上傳的實體檔案檔名
     * @param fileContentType 上傳的實體檔案型態
     * @param fileDescription 上傳的實體檔案說明
     * @return
     * @throws IOException
     */
    public String uploadFileToServer(HttpServletResponse response,String filePath, File file, String fileFileName, String fileContentType, String fileDescription) throws IOException{
        
        String saveFileName = "";
        String showFileDescript = fileDescription.isEmpty()?fileFileName:fileDescription;
        String uploadFileGson="";
        InputStream is = null;
        OutputStream os = null;
        int BUFFER_SIZE = 8 * 1024;
        int fileSize=0;
        
        
        Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
        Map<String,Object> rowAttribute = new HashMap<String,Object>();
        List<Map<String,Object>> fileAttribute = new ArrayList<Map<String,Object>>();
        Map<String,Object> itemCategory = new HashMap<String,Object>();
        
        String osName = System.getProperty("os.name");
        if (!osName.equals("Linux")) {
            filePath = "C:" + filePath;
        }
        try{
            //檢查是否有此Folder:filePath, 若無則建立
            File filePathIsFolder = new File(filePath);
            if (!filePathIsFolder.isDirectory())
                filePathIsFolder.mkdirs();
            //取得上傳檔案的附檔名
            String extension = "";
            if (fileFileName.indexOf('.') > -1){
                String[] tmp = fileFileName.split("\\.");
                extension = "." + tmp[tmp.length - 1];
            }
            saveFileName = new Date().getTime() + extension;
            
            //開始將檔案讀出並寫入主機            
            is = new FileInputStream(file);
            fileSize=is.available();
            File destFile = new File(filePath, saveFileName);
            os = new FileOutputStream(destFile);
            byte[] buffer = new byte[BUFFER_SIZE];
            while(is.read(buffer)>0){
                os.write(buffer);
            }
            is.close();
            os.close();
            
            //組成 jquery-file-upload 需要的 gson 格式
            itemCategory.put("name", showFileDescript);
            itemCategory.put("size", fileSize);
            itemCategory.put("type", fileContentType);
            itemCategory.put("url", "FileOutput?name="+saveFileName);
            itemCategory.put("deleteUrl", "Index?reqCode=fileDelete&fileFileName="+saveFileName);
            itemCategory.put("deleteType", "POST");
            fileAttribute.add(itemCategory);
            rowAttribute.put("files", fileAttribute);
            
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            if (null!=is){
                is.close();
            }
            if (null!=os){
                os.close();
            }
        }
        //產生 gson 字串
        uploadFileGson=gson.toJson(rowAttribute);
        //回傳 gson 至前端
        gsonOutput(response,uploadFileGson);
        
        return saveFileName;
    }
    
    /**
     * 在前端產生 Gson String
     * @param response
     * @param gsonString
     */
    public void gsonOutput(HttpServletResponse response, String gsonString){
        PrintWriter writer=null;
        response.setContentType("text/html;charset=UTF-8");
        try {
            writer = response.getWriter();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        writer.print(gsonString);
        writer.flush();
        writer.close();        
    }
}       

 

Step 07: 檔案下載的 class: FileOutput

package com.gussh.common.utils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class FileOutput extends ActionSupport {
    
    static Logger logger = Logger.getLogger(FileOutput.class);
    
    @Resource(name="BA_TOOLS")
    protected BA_TOOLS baTools;
    public HttpServletRequest request = ServletActionContext.getRequest();
    public HttpServletResponse response = ServletActionContext.getResponse();
    
    private InputStream inputStream ;
    private String name;    
    
    public InputStream getInputStream() {        
        
        String filenamedownload = "";
        String filePath="/upload/";        
        String osName = System.getProperty("os.name");
        
        if (!osName.equals("Linux")) {
            filePath = "C:" + filePath;
        }
        
        filenamedownload = filePath+ "/" + this.getName();
        
         try{
             File file = new File(filenamedownload);
             if(file.length()>0)
                 inputStream = new FileInputStream(filenamedownload);
             else
                 inputStream = new ByteArrayInputStream("No Files".getBytes());
         }catch(Exception e){
             e.printStackTrace();
         }
        
        
         //return ServletActionContext.getServletContext().getResourceAsStream(filenamedownload);
         return inputStream;
    }
    
    public String execute() throws Exception {    
        return "success";
    }

    public String getDownloadFileName() {   
          
        String downFileName = name;  
        try {  
            downFileName = new String(downFileName.getBytes(), "ISO8859-1");
        } catch (UnsupportedEncodingException e) {  
            e.printStackTrace();  
        }  
        return downFileName;   
 
    }    
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }       
    
}

 

Step 08: file upload 的 javascript

$(document).ready(function () {
    
    // Initialize the jQuery File Upload widget:
    $('.fileupload').each(function (e, data) {    
        $(this).fileupload({
            dropZone: $(this)            
        });        
        $('#reqCode').val('fileUpload');
    });
    
    /*處理每一個檔案上傳前, 加入單一 fileDescription 的值*/
    $('.fileupload').bind('fileuploadsubmit', function (e, data) {
       
        // 剔除欄位:fileDescription 後, 取得所有要上傳的值
        var allInputs = $( ":input[name!='fileDescription']"  );
        // 抓取 id="template-upload" 裡新增加單一的 input 欄位: fileDescription
        var fileUploadInputs = data.context.find(':input');
        // 兩個 array 再 merge , 就是所有欄位要上傳的所有值
        var inputs = $.merge(allInputs,fileUploadInputs);
        
        if (inputs.filter(function () {
                return !this.value && $(this).prop('required');
            }).first().focus().length) {
            data.context.find('button').prop('disabled', false);
            return false;
        }
        // 上傳的欄位值需要序列化, 才會逐一上傳
        data.formData = inputs.serializeArray();
    });

});

 

大致的作業如上.

 

參考網址:

Setting formData on upload start for each individual file upload

https://struts.apache.org/docs/file-upload.html

 

 

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

在 Struts2 的異常處理有兩種,一種是程式撰寫的邏輯出錯,另一種是找不到 action Name : There is no Action mapped for namespace...,避免系統出錯的改善作法如下:

 

程式撰寫的邏輯出錯:

在 Struts.xml 內加入

<global-results>
    <result name="error">/error.jsp</result>
</global-results>

<global-exception-mappings>
    <exception-mapping exception="java.lang.Exception" result="error"/>            
</global-exception-mappings>

建立 error.jp 檔案

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>An unexpected error has occurred</title>
</head>
<body>

    <h3>The application has malfunctioned(該應用程序出現錯誤)</h3>

    <p>Please contact technical support with the following information(請聯繫資訊單位並提供以下信息):</p>

    <h4>
        Exception Name:<s:property value="exception" />
    </h4>

    <h4>
        Exception Details:<s:property value="exceptionStack" />
    </h4>

</body>
</html>

 

一種是找不到 action Name:

有兩個方法可以解決

第一種是方法利用 default-action-ref:

在 Struts.xml 內加入

<default-action-ref name="UnderConstruction"/>

<action name="UnderConstruction">
   <result>/UnderConstruction.jsp</result>
</action>

建立 UnderConstruction.jp 檔案

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@page import="org.apache.struts2.ServletActionContext"%>
<%@page import="com.opensymphony.xwork2.ActionContext"%>
<%@page import="java.util.*"%>
<%@page import="java.net.*"%>
<%@page import="java.text.MessageFormat"%>
<%@page import="com.gussh.common.utils.*"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>

<%

String username = (String)session.getAttribute("USERNAME");
String password = (String)session.getAttribute("PASSWORD");
String language = (String)request.getSession().getAttribute("loginLanguage");
String progModule = (String)session.getAttribute("progModule");
String actionName= "";
String actionURL= "";


ActionContext actionContext = ServletActionContext.getContext();
actionName = actionContext.getName();

actionURL="http://polinwei.blogspot.tw/login.do";

    
    
%>
<body>

<%if(username != null){%>
    <form name="ssoForm" action="<%=actionURL %>" target='_blank'>
    <input type="hidden" name="username" value="<%=username %>" />
    <input type="hidden" name="password" value="<%=password %>"  />
    <input type="hidden" name="language" value="<%=language %>"  />       
    </form>
    <script type="text/javascript">
    var formObj=document.ssoForm;
    formObj.method='post';
    formObj.submit();
    document.location.href="<%=request.getContextPath()%>/Index?reqCode=moduleSelect&progModule=<%=progModule%>"
    </script>
<% }else{ %>
    <script type="text/javascript">
        window.opener.top.document.location.href="<%=actionURL %>";
        window.opener=null;
        window.open("","_self");
        window.close();
    </script>
<% }%>
</body>
</html>

 

第二種作法則是利用 unknown-handler-stack:

在 Struts.xml 內加入

<struts>
.
.    
   <!-- 使用bean 定義一個UnknownHandler -->  
     <bean type="com.opensymphony.xwork2.UnknownHandler" name="myHandler" class="com.sc.actions.UnderConstructionAction" />
    
   <package name="default" namespace="/" extends="struts-default">
   .
   .
   </package>    
   <!-- Add addition packages and configuration here. -->

     
    <!-- 定義本系統的 UnknownHandler -->        
    <unknown-handler-stack>
       <unknown-handler-ref name="myHandler" />
    </unknown-handler-stack>      
</struts>   

 

class="com.sc.actions.UnderConstructionAction"

package com.gussh.sc.actions;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.ServletDispatcherResult;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.UnknownHandler;
import com.opensymphony.xwork2.XWorkException;
import com.opensymphony.xwork2.config.entities.ActionConfig;


public class UnderConstructionAction implements UnknownHandler {
    // 網頁會使用的 request, response, session
    public HttpServletRequest request = ServletActionContext.getRequest();
    public HttpServletResponse response = ServletActionContext.getResponse();
    public Map<String, Object> session = ActionContext.getContext().getSession();
   
    public ActionConfig handleUnknownAction(String namespace, String actionName)
            throws XWorkException {        

        ActionConfig actionConfig = null;
        request.setAttribute("actionName",actionName);    
        
        return actionConfig;

    }

    public Result handleUnknownResult(ActionContext actionContext,
            String actionName, ActionConfig actionConfig, String resultCode)
            throws XWorkException {
        actionContext.put("action", actionName);  
        actionContext.put("result", resultCode);
        request.setAttribute("actionName",actionName);
        return new ServletDispatcherResult("/templates/SSO/GUSSO.jsp");
    }

    public Object handleUnknownActionMethod(Object action, String methodName)
            throws NoSuchMethodException {
        // TODO Auto-generated method stub
        return null;
    }

}

 

 

參考:

https://struts.apache.org/docs/unknown-handlers.html

https://struts.apache.org/docs/exception-configuration.html

http://terryjs.iteye.com/blog/777999

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

JSP 的 EL 與 JSF 的 EL( 如 JSF EL ( Expression Language ) 的介紹),大致相同,參考 http://penguin1989930.pixnet.net/blog/post/236537248 ,後整理如下:

 

使用EL存取資料
如果想要顯示application隱含物件中的count變數時,可以使用JSP這樣做:
<%=application.getAttribute("count")%>

而也可以透過EL這樣做:
${count}

${applicationScope.count}

您可以發現EL真的讓JSP的程式碼簡潔了許多。其中applicationScope代表示application隱含物件中的資料集合(並不等於application物件),而EL顯示集合的方法有三種:
${applicationScope.count}
${applicationScope['count']}
${applicationScope["count"]}

1.存取資料的預設物件有:

EL預設物件

對應的JSP隱含物件集合

applicationScope

application集合

sessionScope

session集合

pageScope

page集合

requestScope

request集合

pageContext

pageContext物件

存取資料時,如果沒有指定範圍,會依照pageContext >> request >> session >> application的順序來顯示資料,例如:

<%
session.setAttribute("username","jack");
application.setAttribute("username","mary");
%>

${username}


由於session與application兩者都擁有username變數值,所以EL會依照先後順序來顯示資料(session >> application),所以上述程式便會輸出 jack。
如果想要取得web.xml所設定的初始變數值,可以利用initParam預設物件來完成,請看以下範例:

使用JSP

使用EL

<%=application.getInitParameter("host")%>

${initParam}


2. 利用EL接收網頁傳遞過來的資料 

接收網頁傳遞過來的資訊可使用EL所提供的預設物件

EL預設物件

對應的JSP的方法

param

request.getParameter()

paramValues

request.getParameterValues()


如果要顯示網頁傳遞過來的變數:

使用JSP

使用EL

<%=request.getParamater("username")%>

${param.username}

如果要顯示網頁傳遞過來的變數:(該變數為陣列時)

使用JSP

使用EL

<%

String[] paper = request.getParamaterValues("paper");

out.print("第一個項目:"+paper[0]);

%>

${paramValues.paper[0]}

 

3. 利用EL取得cookie資料

如果使用JSP來取得cookie中的username,可以使用以下程式碼:

Cookie[] ck = request.getCookies();
if (ck != null) {
for (int i = 0; i < ck.length; ++i)
if (ck[i].getName().equals("username")) {
out.print(ck[i].getValue());
break;
}
}

但如果使用EL的預設物件-cookie,就可以簡化成:
${cookie.username.value}

 

4. 利用EL取得網頁標頭資訊

取得標頭用EL所提供的預設物件

EL預設物件

對應的JSP的方法

header

request.getHeader()

headerValues

request.getHeaders()

舉例來說,如果想要取得目前網站主機名稱,可以使用以下方法:

使用JSP

使用EL

<%=request.getHeader("host")%>

${header.host}

<%=request.getContextPath() %>

${request.contextPath}

運用如下:

<a href="${request.contextPath}/Home" >Home</a>

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

在 freemark 的頁面要嵌入 action 及 參數( Parameters) 有兩種方式

1. 使用 struts2 tag: action

<img width='100px' src='
    <@s.action name="Picout" executeResult="success">  
           <@s.param name="name">${Session.userInfo['PHOTO_PATH']}</@s.param>  
    </@s.action>  
'/>

 

2. 使用 struts2 tag: url

<img width='100px' src='<@s.url action="Picout"><@s.param name="name">${Session.userInfo['PHOTO_PATH']}</@s.param></@s.url>' />

 

個人建議使用第2種方法較為方便

參考: http://www.mkyong.com/struts2/struts-2-url-tag-example/

struts2:在freemarker頁面取得 Application Cookie Request Session parameter

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

Windows Server 2012 AD 移除 Sub Domain 的方法,有兩種方式:

方法一:利用 ntdsutil 指令

ntdsutil 指令操作說明如下

ntdsUtil_removeSubDomain_description.jpg  

實作如下:

ntDSUtil_renive_domain.png  

若移除不成功,則用 方法二:利用精靈 的強制移除

 

方法二:利用精靈

Step 01: 選擇 啟動[移除角色及功能精靈]

W2k12_AD_Remove01.png

Step 02:將 Active Directiory..的 Check Box 的勾移除,系統跳出提示視窗,選 "移除功能"

W2k12_AD_Remove02.png

Step 03: 再選 "將此網域控制站降級"

W2k12_AD_Remove03.png  

後續可以先嚐試正常的降級方式,若降級不下來,再使用強制降級

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

Java 要對 Windows Server AD (Active Directory) 的認證整合,程式碼如下:

 

Step 01: 準備一個共用函數 LDAP_AUTH_AD

    /**
     * AD LDAP 登入認證
     *
     * @param ldap_url
     *            like ldap://912.168.2.1:389/DC=WEI,DC=COM
     * @param account
     * @param password
     * @return String[2] array 0 :0 success,1 fail,2 LDAP connect fail,3 unknow
     *         error array 1 :useremail
     */
    public String[] LDAP_AUTH_AD(String ldap_url, String account, String password) {
        String[] returnStr = new String[2];
        Hashtable<String, String> env = new Hashtable<String, String>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, ldap_url);
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, account);
        env.put(Context.SECURITY_CREDENTIALS, password);

        LdapContext ctx = null;
        try {
            ctx = new InitialLdapContext(env, null);
            returnStr[0] = "0";

            SearchControls searchCtls = new SearchControls();
            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            String searchFilter = "(sAMAccountName=" + account + ")";

            String searchBase = "";
            int totalResults = 0;

            String returnedAtts[] = { "mail" };
            searchCtls.setReturningAttributes(returnedAtts);
            try {
                NamingEnumeration answer = ctx.search(searchBase, searchFilter, searchCtls);

                while (answer.hasMoreElements()) {
                    SearchResult sr = (SearchResult) answer.next();
                    Attributes Attrs = sr.getAttributes();
                    if (Attrs != null) {
                        try {
                            for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore();) {
                                Attribute Attr = (Attribute) ne.next();
                                for (NamingEnumeration e = Attr.getAll(); e.hasMore(); totalResults++) {
                                    returnStr[1] = e.next().toString();
                                }

                            }
                        } catch (NamingException e) {
                            System.err.println("Throw Exception : " + e);
                        }
                    }
                }
                loger.debug("Number: " + totalResults);
            } catch (Exception e) {
                loger.error("Can't find Email Address");
            }

            return returnStr;
        } catch (javax.naming.AuthenticationException e) {
            returnStr[0] = "1";
            e.printStackTrace();
            return returnStr;
        } catch (javax.naming.CommunicationException e) {
            // System.out.println("Can't connect to ldap server!");
            returnStr[0] = "2";

            return returnStr;
        } catch (Exception e) {
            System.out.println("error");
            e.printStackTrace();
            returnStr[0] = "3";

            return returnStr;
        } finally {
            if (ctx != null) {
                try {
                    ctx.close();
                } catch (NamingException e) {

                }
            }
        }
    }

 

Step 02: 主程式

// 取得認證URL
String LDAP_URL="ldap://192.168.2.1:389/DC=WEI,DC=COM;WEI.COM";
LDAP_URL = LDAP_URL.split(";")[0];;
// 取得該公司網域
String AD_Domain="";
AD_Domain = "@"+LDAP_URL.split(";")[1].trim();

// AD認證方式登入
if(AUTH_METHOD.equalsIgnoreCase("AD") && !isLogin) {
    String[] as = baTools.LDAP_AUTH_AD(LDAP_URL, users.getUserName()+AD_Domain, users.getUserPassword());
    if (as[0].equals("0")) {
        isLogin = true;
        loginResult= SUCCESS;

    }else{
        this.addActionError("帳號登入錯誤");
    }
} // end AD認證方式登入

 

這樣就可以與您的公司的 AD (Active Directory) LDAP認證主機作整合.

程式碼:Java 對於LDAP: Windows Server AD (Active Directory) 的認證整合
http://misforum.ddns.net/forum.php?mod=viewthread&tid=20&fromuid=2
(出處: MISForum 資訊論壇)

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

JBOSS & Wildfly 常用設置

1. JBoss伺服器改成支援外網訪問
standalone.xml文件中找到

<interface name="public">
            <inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>

在這個下面加入

 <interface name="any">
            <any-ipv4-address/>
 </interface>

另外把1改成2
1  <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
2  <socket-binding-group name="standard-sockets" default-interface="any" port-offset="${jboss.socket.binding.port-offset:0}">

或改成

<interface name="public">
    <any-address/>
</interface>

也可以用圖形管理界面來作修改,如下圖,將 Address Wildcard 設為:Any Address,並將 Inet Address 設為空值,不然會有錯誤。

JBoss interface 對外  

修改管理介面的網址限制

jboss_manageIP  
 
2.
訪問埠的更改
<socket-binding name="http" port="${jboss.http.port:80}"/>
 
3.
改為可以修改JSP頁面不用重啟

<servlet-container name="default">
    <jsp-config/>
    <websockets/>
</servlet-container>

改為

<servlet-container name="default">
      <jsp-config development="true"/>
</servlet-container>

 
4.
部署的程式不用wildfly內置CXF
 在應用的WEB-INF目錄下面增加該檔:jboss-deployment-structure.xml

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
    <deployment>
  <!-- exclude-subsystem prevents a subsystems deployment unit processors running on a deployment -->
     <!-- which gives basically the same effect as removing the subsystem, but it only affects single deployment -->
        <exclude-subsystems>
            <subsystem name="webservices" />
        </exclude-subsystems>
    </deployment>
</jboss-deployment-structure>

 

參考:

http://misforum.ddns.net/forum.php?mod=viewthread&tid=19

http://my.oschina.net/zhaoqian/blog/366406

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

在撰寫程式時,對於刪除資料前應該是先詢問使用者,以往都是跳出一個詢問視窗,但現在的流覽器大都會阻隔,在導入 Bootstrap 的 framework 後,可以加入 bootstrap-dialog.js 的 plug-in 來強化程式的友善化。效果如下:

 

  • 查詢後的畫面

beforeDel

  • 按下刪除時的詢問視窗

askDel 

 

作法如下:

Step 01:客制一個 java script

// 詢問Y/N 視窗
function dialogYN(formId,dialogType,title,message){
    
    BootstrapDialog.show({
        type: dialogType,
        title: title,
        message: message,            
        closable: false,
        buttons: [{
                label: 'No',
                action: function(dialog) {                        
                    dialog.close();
                }
            }, {
                label: 'Yes',
                cssClass: 'btn-primary',
                action: function(dialog) {
                    dialog.close();
                    $(formId).submit();
                }
            }]
    });    

}

參數:

formId: 回覆為 Yes 後要執行的 form id

dialogType: 詢問視窗的型態有 'type-default' , 'type-info' , 'type-primary' , 'type-success' , 'type-warning' , 'type-danger'

title: dialog 視窗的 title

message: 要顯示的內容

 

Step 02:在 Struts 2 的 Tag 中的用法

<s:submit name="usersSubmit" value="delDataForm" key="display.delete" onclick="$('#reqCode').val('delDataForm');return dialogYN('#UsersTagAction','type-danger','%{getText('display.windowTitle.delConfirm')}','%{getText('msg.common.confirm')}')"/>

為了多國語言的顯示,需要用 getText 配合 EL 的方法來作,如:'%{getText('display.windowTitle.delConfirm')}'

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

Struts 2 對於 Interceptor 攔截器的基本概念與實作 的瞭解後,我們現在來作一下 Interceptor 在 Struts 2 上的基本運用。

首先建立一個 class : com.test.interceptor.MyInterceptor 並且 implements Interceptor,這個 Interceptor 是個 Interface,所以需要實作三個 method:init()、destroy()、intercept(ActionInvocation invocation),其中只有 intercept(ActionInvocation invocation) 需要回傳一個 String 的值,可以利用  invocation.invoke(); 來讓系統自已跳到預設的下一個 Action method。

 

package com.test.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class MyInterceptor implements Interceptor {

    @Override
    public void destroy() {
        System.out.println("MyInterceptor destroy()");

    }

    @Override
    public void init() {
        System.out.println("MyInterceptor Init()");
        
    }

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        System.out.println("MyInterceptor:"+invocation.invoke());
        
        return invocation.invoke();
    }

}

 

再來對 struts.xml 加入自建的 interceptor,在 <interceptors>...</interceptors> 中是定義我們自建的 Interceptor ,讓 Struts 知道有這一個 Interceptor (攔截器),然後再對要攔截的Action name 作設定。

要注意的是,因為我們的 <package name="test" 是 extends="struts-default" ,而 struts-default.xml (在struts2-core-2.x.x.jar 裡預設的) 的預設 Interceptor (攔截器) 是defaultStack,若沒加入它,則系統會停在我們自建的 Interceptor (攔截器),而不會繼續往下執行 validate() -> execute()...等相關的 method()。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <package name="test" namespace="/test" extends="struts-default">

        <interceptors>
            <interceptor name="myInterceptor" class="com.test.interceptor.MyInterceptor"></interceptor>       

        </interceptors>

        
        <!-- Spring Testing -->
        <action name="userLogin_*" method="{1}" class="testUserLogin">
            <result name="input">userLogin.jsp</result>
            <result name="success">eip.jsp</result>
       
            <interceptor-ref name="myInterceptor"/>
            <interceptor-ref name="defaultStack"/>
       
        </action>  

        <!-- Add additional "example" package actions here. -->

    </package>
</struts>

 

上面的設定,也可以用 Interceptor Stock 來達成,如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <package name="test" namespace="/test" extends="struts-default">

        <interceptors>
            <interceptor name="myInterceptor" class="com.test.interceptor.MyInterceptor"></interceptor>
        
            <interceptor-stack name="testStock">
                <interceptor-ref name="myInterceptor"/>
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>
        </interceptors>      
        
        <!-- Spring Testing -->
        <action name="userLogin_*" method="{1}" class="testUserLogin">
            <result name="input">userLogin.jsp</result>
            <result name="success">eip.jsp</result>  
            
            <interceptor-ref name=name="testStock">
        </action>  

        <!-- Add additional "example" package actions here. -->

    </package>
</struts>

 

或者是利用 default-interceptor-ref 來對全部的 Action Name 作 Interceptor (攔截器),如下:

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <package name="test" namespace="/test" extends="struts-default">

        <interceptors>
            <interceptor name="myInterceptor" class="com.test.interceptor.MyInterceptor"></interceptor>
        
            <interceptor-stack name="testStock">
                <interceptor-ref name="myInterceptor"/>
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="testStock"></default-interceptor-ref>
        
        <!-- Spring Testing -->
        <action name="userLogin_*" method="{1}" class="testUserLogin">
            <result name="input">userLogin.jsp</result>
            <result name="success">eip.jsp</result>              
            
        </action>  

        <!-- Add additional "example" package actions here. -->

    </package>
</struts>

 

參考:

http://struts.apache.org/maven/index.html

http://struts.apache.org/maven/xwork-core/apidocs/index.html

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

XAMPP 是一套整合 Apache、PHP、MySQL、Mercury Mail Transport System、FileZilla FTP Server、Tomcat...等的服務應用系統,讓您可以專心在系統程式開發上,若在開發的應用系統中有需要發信時而不想自行管理 Mail Server 時,可以利用內附的 sendmail 結合 gmail 來達成。

 

主要修改的地方有二個設定:

第一個設定檔:修改 \xampp\php\php.ini

[mail function]
; XAMPP: Comment out this if you want to work with an SMTP Server like Mercury
; SMTP = localhost
; smtp_port = 25

; For Win32 only.
; http://php.net/sendmail-from
;sendmail_from = postmaster@localhost

; XAMPP IMPORTANT NOTE (1): If XAMPP is installed in a base directory with spaces (e.g. c:\program files\xampp) fakemail and mailtodisk do not work correctly.
; XAMPP IMPORTANT NOTE (2): In this case please copy the sendmail or mailtodisk folder in your root folder (e.g. C:\sendmail) and use this for sendmail_path.  
 
; XAMPP: Comment out this if you want to work with fakemail for forwarding to your mailbox (sendmail.exe in the sendmail folder)
sendmail_path = "\"\xampp\sendmail\sendmail.exe\" -t"

; XAMPP: Comment out this if you want to work with mailToDisk, It writes all mails in the \xampp\mailoutput folder
;sendmail_path = "\xampp\mailtodisk\mailtodisk.exe"

; Force the addition of the specified parameters to be passed as extra parameters
; to the sendmail binary. These parameters will always replace the value of
; the 5th parameter to mail(), even in safe mode.
;mail.force_extra_parameters =

; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename
mail.add_x_header = Off

; Log all mail() calls including the full path of the script, line #, to address and headers
mail.log = "\xampp\php\logs\php_mail.log"

 

第二個設定檔:修改 \xampp\sendmail

; configuration for fake sendmail

; if this file doesn't exist, sendmail.exe will look for the settings in
; the registry, under HKLM\Software\Sendmail

[sendmail]

; you must change mail.mydomain.com to your smtp server,
; or to IIS's "pickup" directory.  (generally C:\Inetpub\mailroot\Pickup)
; emails delivered via IIS's pickup directory cause sendmail to
; run quicker, but you won't get error messages back to the calling
; application.

smtp_server=smtp.gmail.com

; smtp port (normally 25)

smtp_port=465

; SMTPS (SSL) support
;   auto = use SSL for port 465, otherwise try to use TLS
;   ssl  = alway use SSL
;   tls  = always use TLS
;   none = never try to use SSL

smtp_ssl=auto

; the default domain for this server will be read from the registry
; this will be appended to email addresses when one isn't provided
; if you want to override the value in the registry, uncomment and modify

default_domain=gmail.com

; log smtp errors to error.log (defaults to same directory as sendmail.exe)
; uncomment to enable logging

error_logfile=error.log

; create debug log as debug.log (defaults to same directory as sendmail.exe)
; uncomment to enable debugging

debug_logfile=debug.log

; if your smtp server requires authentication, modify the following two lines

auth_username=yourName@gmail.com
auth_password=yourPassword

; if your smtp server uses pop3 before smtp authentication, modify the
; following three lines.  do not enable unless it is required.

pop3_server=
pop3_username=
pop3_password=

; force the sender to always be the following email address
; this will only affect the "MAIL FROM" command, it won't modify
; the "From: " header of the message content

force_sender=yourName@gmail.com

; force the sender to always be the following email address
; this will only affect the "RCTP TO" command, it won't modify
; the "To: " header of the message content

force_recipient=

; sendmail will use your hostname and your default_domain in the ehlo/helo
; smtp greeting.  you can manually set the ehlo/helo name if required

hostname=

 

重新起動 Apache 服務即可。

PS: Windows 8 的 sendmail 不會正常運作

文章標籤

MIS 發表在 痞客邦 留言(1) 人氣()