在撰寫程式時,對於刪除資料前應該是先詢問使用者,以往都是跳出一個詢問視窗,但現在的流覽器大都會阻隔,在導入 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) 人氣()

Apache 利用 mod_rewrite 做到網址轉換達成SEO優化 我們達成了 SEO 的優化,但當刷新頁面很多次時卻有時會出現空白的頁面,將 php 程式段的偵錯模式打開 error_reporting(E_ALL); 會出現下列的錯誤訊息。

Fatal error: Uncaught --> Smarty: unable to write file /xampp/htdocs/myweb/smarty/templates_c\8c6924ac7efe8f944a5a8a181c85433787f58f0c.file.home_index.html.cache.php <-- thrown in D:\xampp\htdocs\myweb\includes\smarty\libs\sysplugins\smarty_internal_write_file.php on line 74

 

此原因是因為同時要寫入 cache file: home_index.html.cache.php 時發生了 lock 的事件。為避免這種情形發生,可以將 Smarty 的設定值修改如下即可。

 

    error_reporting(E_ALL); //     測試用:E_ALL ; 上線用:E_WARNING

    
    //定義 Smarty的參數
    $smartyTpl = new Smarty();
    
    /*smarty v3 的寫法*/
    $smartyTpl->setTemplateDir(HOST_ROOT . "/smarty/templates/" )
                 ->setCompileDir(HOST_ROOT . "/smarty/templates_c/")
                 ->setConfigDir(HOST_ROOT . "/smarty/configs/")
                 ->setCacheDir(HOST_ROOT . "/smarty/cache/")
                 ->addPluginsDir(HOST_ROOT . "/smarty/plugins/");
   
    $smartyTpl->debugging = false; // true | false;
    //下列參數用預設值即可
    //$smartyTpl->caching = true;
    //$smartyTpl->cache_lifetime = 120;
    //$smartyTpl->force_compile = true;  // 若為 false 則 apache 的 mod_rewrite 做到網址轉換達成SEO優化 不正常
    //$smartyTpl->compile_check = true;
文章標籤

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

Struts 2 支援 POJO 的程式撰寫,所以可以指定 Action Method 來執行您在 struts.xml 中的設定。

<action name="userLogout" method="logout" class="com.gu.EipLogin">
     <result>eip_home.jsp</result>
</action>

 

在 Action Class : com.gu.EipLogin 的程式段

    public String logout(){
        session.clear();
        System.out.println("logout method");
        return SUCCESS;
    }

 

加入 validate() 的  this.addFieldError(...) 或 this.addActionError(...) 後

    @Override
    public void validate() {
        // TODO Auto-generated method stub
        super.validate();
        boolean isInvalidError = false;
        if (isInvalid(getUserName())){
            this.addFieldError("userName", this.getText("userName.error") );
            isInvalidError = true;
        }
        if (isInvalid(getPassword())){
            this.addFieldError("password", this.getText("password.error") );
            isInvalidError = true;
        }
        if (isInvalidError){
            this.addActionError(getText("errors.general"));
        } else {
            session.put("userName", getUserName());
            session.put("login", true);
        }
    }

 

卻發生了錯誤訊息:

Struts Problem Report

Struts has detected an unhandled exception:

Messages:
  • No result defined for action com.gu.EipLogin and result input

 

原因是 Struts 2 進入 Action 時,會先作 validate() ,沒有錯誤後才會執行後續的 method 如: execute()....等,若有錯誤則返回 <result name="input">...</result>; 所以當要執行指定的 method : logout() 前,發生了錯誤會返回預設的 <result name="input">...</result>,但我們又沒有指定,所以才會發生錯誤。

解決的方法是在 logout 的 method 上加入annotation: @SkipValidation ,指示此 method : logout() 不需作 validate() 即可。

    @SkipValidation
    public String logout(){
        session.clear();
        System.out.println("logout method");
        return SUCCESS;
    }

 

 

文章標籤

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

Struts 2 在 struts2-core-2.x.x.jar 的 struts-default.xml 中也設定了許多的 Interceptor 攔截器,Interceptor 攔截器的基本概念大致整理如下:

1. 要有目標對象

2. 攔截器本身,在攔截器本身安插要執行的作業

3. 由 java.lang.reflect.InvocationHandler 來讓 目標對象 與 攔截器 產生關連

4. 由 代理 java.lang.reflect.Proxy 來執行,用來產生動態對象

 

依上面的概念來實作如下:

Step 01: 建立一個 Interface: TargetProvider.java 及實作它: TargetImpl.java

TargetProvider.java

package com.test.interceptor;

public interface TargetProvider {

    public void doExecute();
}

 

TargetImpl.java

package com.test.interceptor;

public class TargetImpl implements TargetProvider {

    @Override
    public void doExecute() {
        // TODO Auto-generated method stub
        System.out.println("do Execute");

    }

}

 

Step 02: 建立Interceptor 攔截器本身:TargetInterceptor.java,並在攔截器本身安撰寫想要執行的作業

package com.test.interceptor;

public class TargetInterceptor {

    public void beforeExecute(){
        System.out.println("before Execute");
    }
    
    public void afterExecute(){
        System.out.println("after Execute");
    }
}

 

由上可以得知,目前 TargetImpl.javaTargetInterceptor.java 並沒有關連

 

Step 03: 建立 java.lang.reflect.InvocationHandler :TargetHandler.java  , 利用 invoke(Object proxy, Method method, Object[] args) 方法讓 TargetImpl.javaTargetInterceptor.java 兩者產生關連

TargetHandler.java

package com.test.interceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class TargetHandler implements InvocationHandler {
    
    private Object object;
    private TargetInterceptor targetInterceptor = new TargetInterceptor();
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        // TODO Auto-generated method stub
        
        Object result = null;
        
        targetInterceptor.beforeExecute();
        
        result = method.invoke(object, args);
        
        targetInterceptor.afterExecute();
        
        return result;
    }
    
    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }    

}

 

Step 04: 再透過 java.lang.reflect.Proxy: TargetProxy.java 的代理(Proxy) 動態產生新的 ProxyInstance,來執行攔截器作業

package com.test.interceptor;

import java.lang.reflect.Proxy;

public class TargetProxy {

    public Object getProxy(Object object){
        
        TargetHandler targetHandler = new TargetHandler();
        targetHandler.setObject(object);
        
        return Proxy.newProxyInstance(TargetImpl.class.getClassLoader(), object.getClass().getInterfaces(), targetHandler);
        
    }
}

 

step 05: 最後建立一個 Class: Client.java 來作測試

package com.test.interceptor;

public class Client {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TargetProvider target = new TargetImpl();
        TargetProxy targetProxy = new TargetProxy();
        
        TargetProvider proxy = (TargetProvider) targetProxy.getProxy(target);
        proxy.doExecute();
    

    }

}

 

執行 Class: Client 的結果如下:

before Execute
do Execute
after Execute

所以可以得知:在目標對象 Object: TargetProvider target ,透過代理 Proxy:  TargetProxy targetProxy 執行時,會動態產生新的 ProxyInstance,並藉由動態產生新的 ProxyInstance 間接讓 InvocationHandlerinvoke() 方法,使得 目標對象 Object: TargetProvider target 與攔截器 Interceptor 攔截器:TargetInterceptor 產生關連 ,因此可以作到我們想要攔截到目標對象時,想要多作的作業。

 

文章標籤

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

Struts 2 要與 Spring 結合並不難,因為 Struts 2 本身就已經預留介面,在 struts2-core-2.x.x.jar 裡的 org.apache.struts2.default.properties 有這一段設定

### if specified, the default object factory can be overridden here
### Note: short-hand notation is supported in some cases, such as "spring"
###       Alternatively, you can provide a com.opensymphony.xwork2.ObjectFactory subclass name here
# struts.objectFactory = spring

### specifies the autoWiring logic when using the SpringObjectFactory.
### valid values are: name, type, auto, and constructor (name is the default)
struts.objectFactory.spring.autoWire = name

 

現在來實作一下:

Step 01: 建立一個帳號登入的 userLogin.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sj" uri="/struts-jquery-tags" %>
<%@ taglib prefix="sb" uri="/struts-bootstrap-tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
    <!-- 設定 base patch  
    if you want to set a base path for all relative links so that you don't need to repeat
    ${pageContext.request.contextPath} in every relative link, use the <base> tag.
    This way every relative link (i.e. not starting with / or a scheme) will become relative to the <base>.
    -->
    <c:set var="url">${pageContext.request.requestURL}</c:set>
    <base href="${fn:substring(url, 0, fn:length(url) - fn:length(pageContext.request.requestURI))}${pageContext.request.contextPath}/" />    
    <sj:head jqueryui="false"/>
    <sb:head includeScripts="true" includeScriptsValidation="false" includeStyles="true" />    
    
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="keywords" content="struts2, twitter, bootstrap, plugin, showcase" />
    <meta name="description" content="Enable Client Side Validation - Struts2 Bootstrap Plugin" />
    
    <!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
    <!--[if lt IE 9]>
    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->

     <!-- Custom styles for this template
    <link href="css/Cosmo/bootstrap.min.css" rel="stylesheet">
    <link href="css/homepage.css" rel="stylesheet">
    -->
<title>User login</title>
</head>
<body>

<div class="container">
    <div class="row">
        <div class="col-md-6">
            Hi Welcome !!
        </div>
        <div class="col-md-6">

            <h1>歡迎光臨  </h1>
            <p>請輸入您的帳號</p>
            <s:actionmessage theme="bootstrap"/>
            <s:actionerror theme="bootstrap"/>


            <!--            
            <s:fielderror theme="bootstrap"/>

            <s:if test="hasActionErrors()">
               <div class="errors">
                  <s:actionerror/>
               </div>
            </s:if>           
            <s:if test="hasActionMessages()">
               <div class="welcome">
                  <s:actionmessage/>
               </div>
            </s:if>
             -->

            
            <s:form action="userLogin" theme="bootstrap" class="form-signin">
                <s:textfield key="loginName" />                
                <s:password key="password" />
                <s:submit cssClass="btn btn-primary"/>
            </s:form>

        </div>
    </div>

    <footer class="footer">
        <p class="pull-right"><a href="#">Back to top</a></p>        
    </footer>

</div>
<!-- /container -->

</body>
</html>

 

Step 02: 建立對應的 userLogin Action Class: com.gu.test.spring.LoginAction

package com.gu.test.spring;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {
    private String loginName;
    private String password;
    
    public String getLoginName() {
        return loginName;
    }
    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    
    public String execute() throws Exception {
        if (isInvalid(getLoginName()))
            return INPUT ;
        if(isInvalid(getPassword()))
            return INPUT;  
        
        return SUCCESS;
    }
    
    private boolean isInvalid(String str){
        return ( str==null || str.length()==0 );
    }
    
    @Override
    public void validate() {
        // TODO Auto-generated method stub
        super.validate();
        boolean isInvalidError = false;
        if (isInvalid(getLoginName())){
            this.addFieldError("loginName", this.getText("loginName.error") );
            isInvalidError = true;
        }
        if (isInvalid(getPassword())){
            this.addFieldError("password", this.getText("password.error") );
            isInvalidError = true;
        }
        if (isInvalidError){
            this.addActionError(getText("errors.general"));
        }
        
    }
}

 

Step 03: 利用Maven 來加入 Spring 的 Jar 檔. 可以參考 http://mvnrepository.com/artifact/org.apache.struts/struts2-spring-plugin

<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-spring-plugin</artifactId>
    <version>2.3.16.3</version>
</dependency>

 

Step 04: 配置 Struts & Spring : 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">
        
    <!--加入 Spring -->    
    <constant name="struts.objectFactory" value="spring" />
<struts>
    <package name="test" namespace="/test" extends="struts-default">

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

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

    </package>
</struts>

這裡的 class="userLogin" 已轉由 Spring 的介面來接手,因此在 Spring 的 applicationContext.xml 要有 bean id="userLogin" 來承接,並指定 class="com.gu.test.spring.LoginAction"

 

Step 05: 配置 Struts & Spring : applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userLogin" class="com.gu.test.spring.LoginAction" scope="prototype"/>
    
</beans>

 

Step 06: 配置 Struts & Spring : web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="struts_blank" version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <display-name>Struts Blank</display-name>

<!-- Context Configuration locations for Spring XML files -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>


  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>
      org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
    </filter-class>
  </filter>

  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
    

  <!-- 啟動  Spring Bean Configure the Spring listener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>  
 
</web-app>

 

登入 http://localhost:8080/guMIS/test/userLogin_input 測試,這樣就可以運作正常了。

文章標籤

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

JBoss EAP 6.x 上要建立 Oracle DataBase 的 Java Naming and Directory Interface (JNDI) 作法分三個步驟如下:

Step 01: 在 $JBOSS_HOME 目錄 modules 下建立 oracle 相關資訊

$ mkdir -p $JBOSS_HOME/modules/com/oracle/main/
$ touch $JBOSS_HOME/modules/com/oracle/main/module.xml

 Step 02: 維護 $JBOSS_HOME/modules/com/oracle/main/module.xml 內容如下

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="com.oracle">  
    <resources>  
        <resource-root path="ojdbc6.jar"/>  
    </resources>  
    <dependencies>  
        <module name="javax.api"/>  
        <module name="javax.transaction.api"/>  
    </dependencies>  
</module>

Oracle DB 的 JDBC Jar 檔 ojdbc6.jar 可以從 Oracle Database 11g Release 2 JDBC Drivers 下載,並將下載的檔案ojdbc6.jar 放在 $JBOSS_HOME/modules/com/oracle/main 裡。

 

Step 03: 這裡以 JBoss EAP standalone Mode 作為範例,修改 $JBOSS_HOME/standalone/configuration/standalone.xml

<profile>
...
<subsystem xmlns="urn:jboss:domain:datasources:1.1">
    <datasources>
        ...               
      <datasource jndi-name="java:/xe" pool-name="xe" enabled="true">
          <connection-url>jdbc:oracle:thin:@127.0.0.1:1521:XE</connection-url>
          <driver>oracle</driver>
          <pool>
              <min-pool-size>10</min-pool-size>
              <max-pool-size>200</max-pool-size>
              <prefill>true</prefill>
          </pool>
          <security>
              <user-name>system</user-name>
              <password>oracle</password>
          </security>
      </datasource>
        <drivers>
            ...
            <driver name="oracle" module="com.oracle">
                <datasource-class>oracle.jdbc.driver.OracleDriver</datasource-class>
            </driver>
        </drivers>
    </datasources>
</subsystem>
</profile>

 

再重啟 JBoss EAP standalone Mode: $JBOSS_HOME/bin/standalone.bat 即可

文章標籤

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

環境:

EBS : R11.5.10

JDeveloper: p8751878_GENERIC.zip 解壓至 D:\OAF_R11i

實作:

Step 01: 準備好程式檔案:HelloWorldPG.xml & HelloWorldMainCO.java

OAF_R11_Hello_01  

HelloWorldPG.xml

<?xml version = '1.0' encoding = 'UTF-8'?>
<!-- dbdrv: exec java oracle/jrad/tools/xml/importer XMLImporter.class java &phase=dat+24 checkfile:~PROD:~PATH:~FILE &fullpath:~PROD:~PATH:~FILE -username &un_apps -password &pw_apps -dbconnection &jdbc_db_addr  -userId "1" -rootPackage /oracle/apps/~PROD  -rootdir &fullpath:~PROD:mds:directory  -->
<page xmlns:jrad="http://xmlns.oracle.com/jrad" xmlns:oa="http://xmlns.oracle.com/oa" xmlns:ui="http://xmlns.oracle.com/uix/ui" version="9.0.3.8.13_1579" xml:lang="en-US" xmlns:user="http://xmlns.oracle.com/jrad/user" xmlns="http://xmlns.oracle.com/jrad" file-version="$Header$">
   <content>
      <oa:pageLayout id="PageLayoutRN" windowTitle="Polin-Demo: Hello World Window Title" title="Polin-Demo:Hello World Page Header" amDefName="oracle.apps.fnd.framework.server.OAApplicationModule">
         <ui:corporateBranding>
            <oa:image id="corporateBrandingImage" source="/OA_MEDIA/FNDSSCORP.gif"/>
         </ui:corporateBranding>
         <ui:contents>
            <oa:messageComponentLayout id="MainRN" controllerClass="polin.oracle.apps.ak.demo.webui.HelloWorldMainCO">
               <ui:contents>
                  <oa:messageTextInput id="HelloName" prompt="Name" columns="20" maximumLength="50"/>
                  <oa:messageLayout id="ButtonLayout">
                     <ui:contents>
                        <oa:submitButton id="Go" use="/oracle/apps/fnd/attributesets/Buttons/Go"/>
                     </ui:contents>
                  </oa:messageLayout>
               </ui:contents>
            </oa:messageComponentLayout>
         </ui:contents>
      </oa:pageLayout>
   </content>
</page>

HelloWorldMainCO.java

/*===========================================================================+
 |   Copyright (c) 2001, 2005 Oracle Corporation, Redwood Shores, CA, USA    |
 |                         All rights reserved.                              |
 +===========================================================================+
 |  HISTORY                                                                  |
 +===========================================================================*/
package polin.oracle.apps.ak.demo.webui;

import oracle.apps.fnd.common.VersionInfo;
import oracle.apps.fnd.framework.webui.OAControllerImpl;
import oracle.apps.fnd.framework.webui.OAPageContext;
import oracle.apps.fnd.framework.webui.beans.OAWebBean;
import oracle.apps.fnd.framework.OAException;

/**
 * Controller for ...
 */
public class HelloWorldMainCO extends OAControllerImpl
{
  public static final String RCS_ID="$Header$";
  public static final boolean RCS_ID_RECORDED =
        VersionInfo.recordClassVersion(RCS_ID, "%packagename%");

  /**
   * Layout and page setup logic for a region.
   * @param pageContext the current OA page context
   * @param webBean the web bean corresponding to the region
   */
  public void processRequest(OAPageContext pageContext, OAWebBean webBean)
  {
    super.processRequest(pageContext, webBean);
  }

  /**
   * Procedure to handle form submissions for form elements in
   * a region.
   * @param pageContext the current OA page context
   * @param webBean the web bean corresponding to the region
   */
  public void processFormRequest(OAPageContext pageContext, OAWebBean webBean)
  {
    super.processFormRequest(pageContext, webBean);
    if (pageContext.getParameter("Go") != null)
      {       
     String userContent = pageContext.getParameter("HelloName");  
     String message = "Hello, " + userContent + "!";
          throw new OAException(message, OAException.INFORMATION);
                  }
  }

}

 

Step 02:  Import OA Page to MDS

R11i 的 import.bat 是在目錄 D:\OAF_R11i\jdevbin\jdev\bin 下:

D:\OAF_R11i\jdevbin\jdev\bin\import.bat D:\OAF_R11i\jdevhome\jdev\myprojects\polin\oracle\apps\ak\demo\webui\HelloWorldPG.xml -rootdir D:\OAF_R11i\jdevhome\jdev\myprojects -username apps -password apps -dbconnection "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=erpdb.polin.com)(PORT=1522))(CONNECT_DATA=(SID=TEST)))"

 

OAF_R11_Hello_02  

檢查 MDS 是否有此筆資料

SET serveroutput ON;
BEGIN
  jdr_utils.printdocument('/polin/oracle/apps/ak/demo/webui/HelloWorldPG');
EXCEPTION
WHEN OTHERS THEN
  DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;

 若要刪除此筆 MDS,則可以用 jdr_utils.DeleteDocument 的函數

begin
  jdr_utils.DeleteDocument( '/polin/oracle/apps/ak/demo/webui/HelloWorldPG' ) ;
end ;
/

 

Step 03: FTP Upload class file to $JAVA_TOP

利用 FTP 工具將開發好所有 Package 的 class files,從開發本機目錄:D:\OAF_R11i\jdevhome\jdev\myclasses\polin\oracle\apps\ak\demo\webui,上載到 EBS 主機上的 $JAVA_TOP 相對應的目錄下,因為撰寫 Java 程式的 Package 為 polin.oracle.apps.ak.demo.webui ,所以 EBS 主機相對應的目錄為 $JAVA_TOP/polin/oracle/apps/ak/demo/webui

OAF_R11_Hello_03  
  

Step 04: Configure the Funtions

先規劃 Funtions 的相關屬性再作設定,HTML Call 則是 Step03 中,class file 上載到 EBS 主機上的 $JAVA_TOP 相對應的目錄下,此例為/polin/oracle/apps/ak/demo/webui/HelloWorldPG,所以HTML Call:OA.jsp?page=/polin/oracle/apps/ak/demo/webui/HelloWorldPG

Function User Function Name Description Function Type HTML Call
POLIN_OAF POLIN_OAF Polin OAF Demo SSWA jsp function

OA.jsp?page=/polin/oracle/apps/ak/demo/webui/HelloWorldPG

 

Step 05:Configure Menu

先規劃 MENU 的相關屬性再作設定

Menu Header

Menu User Menu Name Menu Type Description
POLIN_MENU POLIN_MENU Standard Polin OAF Menu

Menu Detail

Seq Prompt Submenu Function Description
10 Polin_OAF_HelloWorld   POLIN_OAF Polin_OAF_HelloWorld

 

Step 06:Configure Responsibility

OAF_R11_Hello_04  

 

這樣就可以測試正常了

 

 

文章標籤

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

在這篇文章:Apache 利用 mod_rewrite 做到網址轉換達成SEO優化 說到使用此方法的好處,在 Struts2 中也可以利用 WildcardMappings 來達成 SEO 優化,舉下列例子來說明:

原來:http://localhost:8080/guEBS/guWeb/userChooseLang?lang=chinese

變成:http://localhost:8080/guEBS/guWeb/userChooseLang/chinese

 

Step 1:在 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>    
    <constant name="struts.mapper.alwaysSelectFullNamespace" value="false"/>
    <constant name="struts.enable.SlashesInActionNames" value="true"/>
    <constant name="struts.patternMatcher" value="namedVariable"/>        
    
    <package name="guWeb" namespace="/guWeb" extends="struts-default">  

        <action name="userChooseLang/{lang}" class="com.gu.web.GUsetLang">    
            <result>/guWeb/Home.jsp</result>        
        </action>  


    </package>
    <!-- Add addition packages and configuration here. -->
</struts>

 

Step 2:Action Class: com.gu.web.GUsetLang.java

package com.gu.web;

public class GUsetLang extends ActionSupport {

    private String lang;
    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        String sLang = "chinese".equalsIgnoreCase(getLang()) ? "zh-TW" : "en-US" ;        
        session.put("userLang", sLang);
        super.execute();
        setNavMenu("guWeb");
        return SUCCESS;
    }
    public String getLang() {
        return lang;
    }
    public void setLang(String lang) {
        this.lang = lang;
    }

}

 

Step 3:jsp頁面Home.jsp 的測試

<%@ 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>Insert title here</title>
</head>
<body>
       <h1>Wild Card Value</h1>
       lang: <s:property value="lang"/>
</body>
</html>

 

但要注意,若常數 <constant name="struts.patternMatcher" value="namedVariable"/> 或 <constant name="struts.patternMatcher" value="regex"/> ,則 <action name="demo_*" method="{1}" class="..."> 會無法正常作業,這設定只能二擇一。在 http://struts.apache.org/release/2.2.x/docs/wildcard-mappings.html 有說明。


Only one PatternMatcher implementation can be used at a time. The two implementations included with Struts 2 are mutually exclusive. You cannot use Wildcards and Named Variable patterns at the same application (if that were required, you'd need to create a custom PatternMatcher implementation).

參考:

http://www.struts2.info/blog/better-urls-with-struts2

http://struts.apache.org/release/2.2.x/docs/wildcard-mappings.html

文章標籤

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