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) 人氣()

裝完 JBoss EAP 6.x ,並利用 Eclipse 開發程式除錯 Debug 時,發現一般使用 System.out.println() &  logger.info() 都沒有出現在 Console 中,查了好久才找到正解如下:

1. 在 Eclipse 開發環境:

在 Servers 視窗下的 JBoss EAP Server 點兩下,選擇 Open Launch configuration ,然後在 VM arguments 裡最後加入 -Dorg.jboss.as.logging.per-deployment=false 即可,如下圖:

JBossEAP_Eclipse.png  

這樣訊息就會出來了,但 System.out.print() 仍會不出現,直到下一個 System.out.println() 才會一起出現,這是JBoss EAP 的 Bug.

 

2. 在 JBoss 正式環境的設定:

Step 1 :

修改 $JBOSS_HOME/standalone/configuration/standalone.xml 增加 <use-deployment-logging-config value="false"/> 在 <profile>...</profile> 中如下:

    <profile>
        <subsystem xmlns="urn:jboss:domain:logging:2.0">
              <use-deployment-logging-config value="false"/>
            <console-handler name="CONSOLE">
                <level name="INFO"/>
                <formatter>
                    <named-formatter name="COLOR-PATTERN"/>
                </formatter>
            </console-handler>

 

參考:

http://mariemjabloun.blogspot.tw/2013/11/disable-jboss-eap-6-logging-exclude.html

https://bugzilla.redhat.com/show_bug.cgi?id=1070453

文章標籤

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

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

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

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

 

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

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

MySQL 的 JDBC Jar 檔可以從 http://dev.mysql.com/downloads/connector/j/ 網站下載,並將下載的檔案 mysql-connector-java-x.x.x-bin.jar 放在 $JBOSS_HOME/modules/com/mysql/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:jboss/datasources/ExampleInfinispanDS" pool-name="ExampleInfinispanDS" enabled="true" use-java-context="true" use-ccm="true">
            <connection-url>jdbc:mysql://localhost:3306/EXAMPLEINFINISPAN</connection-url>
            <driver>mysql</driver>
            <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
            <pool>
                <min-pool-size>10</min-pool-size>
                <max-pool-size>100</max-pool-size>
                <prefill>true</prefill>
            </pool>
            <security>
                <user-name>root</user-name>
                <password>root</password>
            </security>
            <validation>
                <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker"/>
                <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter"/>
            </validation>
            <timeout>
                <!-- using default timeout values -->
            </timeout>
            <statement>
                <prepared-statement-cache-size>100</prepared-statement-cache-size>
                <share-prepared-statements>true</share-prepared-statements>
            </statement>
        </datasource>
        <drivers>
            ...
            <driver name="mysql" module="com.mysql">
                <datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlDataSource</datasource-class>
            </driver>
        </drivers>
    </datasources>
</subsystem>
</profile>

 

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

 

 

參考:

http://magnus-k-karlsson.blogspot.tw/2013/08/complete-configuration-of-mysql-5.html

http://www.vogella.com/tutorials/MySQLJava/article.html

https://access.redhat.com/documentation/en-US/JBoss_Enterprise_BRMS_Platform/5/html/BRMS_Administrator_Guide/Configuring_a_Datasource_for_JBoss_Enterprise_Application_Platform_6.html

JBoss EAP 6.1 Administration and Configuration Guide. Chapter 6.6. Datasource Configuration

MySQL 5 Manual. Chapter 22.3.5.1 Driver/Datasource Class Names, URL Syntax and Configuration Properties for Connector/J

文章標籤

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

Struts 2 仍有多語言的支援,相關的文件可以查看 http://struts.apache.org/release/2.2.x/docs/localization.html ,搜尋的順序是:

  1. ActionClass.properties
  2. Interface.properties (every interface and sub-interface)
  3. BaseClass.properties (all the way to Object.properties)
  4. ModelDriven's model (if implements ModelDriven), for the model object repeat from 1
  5. package.properties (of the directory where class is located and every parent directory all the way to the root directory)
  6. search up the i18n message key hierarchy itself
  7. global resource properties

參考網文 Struts 2 – Resource bundle example 的一張圖可以大致瞭解其搜尋順序

 若 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.enable.DynamicMethodInvocation" value="false"/>
    <constant name="struts.devMode" value="true"/>
    <constant name="struts.custom.i18n.resources" value="messages" />  

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

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

        <global-exception-mappings>
            <exception-mapping exception="java.lang.Exception" result="error"/>
        </global-exception-mappings>
      
        <action name="Login_*" method="{1}" class="com.gu.Login">
            <result name="input">/Login.jsp</result>
        </action>
    </package>
</struts>

而 properties 檔:global.properties & package.properties 擺放的位置如下圖:

struts_properties  

所以在 com.gu 裡的 package.properties 內的值就會優先於 global.properties。而 global-resource 的設定可以參考: http://struts.apache.org/release/2.3.x/docs/how-do-i-set-a-global-resource-bundle.html。但個人覺得最好用的是在 struts.xml 中設定 <constant name="struts.custom.i18n.resources" value="messages" />,然後在message.properties 檔作維護就好。

取得的方法有下列幾個方法:

1. Action class:使用函數 getText("key")

public class Login extends ActionSupport{
        ...
        public void validate(){
                if("".equals(getUsername())){
                        addFieldError("username", getText("username.required"));
                }
        }
}

 

2. property tag: property (屬性)的 tag 用 getText("key") 來取值

<s:property value="getText('username')" />

 

3. text tag:text(文字) 的 tag 用 "name" 的屬性來取值

<s:text name="username" />

 

4. Key attribute:以 "key" 的屬性來取值

<s:textfield key="username" />

 

5. I18n tag :指定檔案取值,例如讀取檔案 com.gu.ebs.package.properties

<s:i18n name="com.gu.ebs.package" >
     <s:text name="username" />
</s:i18n>

 

參考:

http://struts.apache.org/release/2.2.x/docs/localization.html

http://www.mkyong.com/struts2/struts-2-resource-bundle-example/

http://www.mkyong.com/struts2/struts-2-key-attribute-example/

 

文章標籤

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