2015年9月24日 星期四

AngularJS Breadcrumb With Route

同步發布於 http://villebez.logdown.com/posts/2015/07/20/angularjs-breadcrumb
AngularJS v1.4.4
Project結構:
-js/app.js
-js/route.js
-js/breadcrumb/directive.js
-js/breadcrumb/factory.js
-js/vendors/angular-route.min.js
-js/vendors/angular.min.js
-template/breadcrumb.html
-template/hello.html
-template/world.html
-template/index.html
-index.html
第一次寫AngularJS文章就挑戰Breadcrumb,寫得非常簡單陽春,
在寫這篇找資料時,意外找到一個更好的做法,提供參考
Auto-breadcrumbs with angular-ui-router
不過我的作法是手動breadcrumbs 冏rz...
那就來獻醜了...
首先呢~當然是看index.html
引入所需要的JS,body就只放breadcrumb directive以及view。

 data-ng-app="bcapp">

 charset="utf-8">
</span>BreadCrumb Demo<span class="nt" style="margin: 0px; padding: 0px; color: rgb(38, 139, 210) !important; font-weight: bold !important;">






-directive></breadcrumb-directive>
data-ng-view>
接著看看app.js、route.js
app 就只有迴圈設定$routeProvider,將route config抽出來至route.js
(function() {
    'use strict';
    angular.module('bcapp', [ 'ngRoute', 'components.breadcrumb' ]).config(configure);
    configure.$inject = [ '$routeProvider' ];
    function configure($routeProvider) {

        // Url 設定
     for ( var locationPath in appConfig.locationConfig) {
            var urlPattern = locationPath;
            var config = appConfig.locationConfig[locationPath];
            $routeProvider.when(urlPattern, config);
        }
    }
})();
route config簡單的設定urlPattern、template與resolve對該頁設定breadcrumb
window.appConfig = window.appConfig || {};
window.appConfig.locationConfig = {
    '/': {
        templateUrl: '/template/index.html',
        resolve : [["Breadcrumbs",function(Breadcrumbs){
            Breadcrumbs.init();
            
        }]]
    },
    '/hello': {
        templateUrl: '/template/hello.html',
        resolve : [["Breadcrumbs",function(Breadcrumbs){
            Breadcrumbs.init();
            Breadcrumbs.push({
                 "name": "Hello",
            });
        }]]
    },
    '/world': {
        templateUrl: '/template/world.html',
        resolve : [["Breadcrumbs",function(Breadcrumbs){
            Breadcrumbs.init();
            Breadcrumbs.push({
                 "name": "World",
            });
        }]]
    }
};
再來看看breadcrumb directive.js, factory.js
directive很基本,指定restrict,載入templateUrl,注入Breadcrumbs factory並set scope.breadcrumbs讓html可以使用這個factory
(function(){
    'use strict';
    angular.module('components.breadcrumb',[]).directive('breadcrumbDirective', Directive);
    
    Directive.$inject = 
        ['Breadcrumbs'];
    
    function Directive(Breadcrumbs) {
        var directive = {
            scope: {
                
            },
            restrict:    'E',
            templateUrl : '/template/breadcrumb.html',
            link : link  
        };
        
        return directive;
        
        function link(scope, elem, attrs, ctrl) {
            scope.breadcrumbs = Breadcrumbs;
        }
    }
})();
factory提供了幾個function
init初始化
set傳入Array設定整個breadcrumb
push傳入一筆資料進入Array
getAll取得整個Array
getFirst拿到第一筆資料
(function(){
    'use strict';
    angular
        .module('components.breadcrumb')
        .factory('Breadcrumbs', factory);

    factory.$inject = [];

    function factory() {
        var self = this;
        self.breadcrumbs  = [];

        // Interface
     self.init = init;
        self.set  = set;
        self.push = push;
        self.getAll = getAll;
        self.getFirst = getFirst;

        // Implement
     function init(){
            self.breadcrumbs =[{
                 "name": "首頁",
                 "path": "#/"
            }];
        }
        
        function set (urls) {
            self.breadcrumbs = urls;
        }
        
        function push (url){
            self.breadcrumbs.push(url);
        }
        
        function getAll(){
            return self.breadcrumbs;
        }
        
        function getFirst(){
            return self.breadcrumbs[0] || {};
        }
        
        return self;
    }
})();
最後就是四個template,其實沒什麼東西,只是為了呈現不同頁面與文字
-template/breadcrumb.html
class="breadCrumb">
  • ng-repeat="breadcrumb in breadcrumbs.getAll()" class="node"> -switch on="$last"> ng-switch-when="true">{{breadcrumb.name }} ng-switch-default> href="{{ breadcrumb.path }}" class="hand">{{ breadcrumb.name }} </ng-switch> ng-if="!$last" class="divider">>
  • -template/hello.html
    Hello
    
    -template/world.html
    world
    
    -template/index.html

    2015年5月22日 星期五

    Resolved : Set the Database Default Value in a Hibernate/JPA Save Persist

    Using JPA (with Hibernate), I was inserting a record in my database. 
    In my table, one column is defined with a DEFAULT Value.
    But when I insert a save, persist my record, JPA put it as NULL.
    So using JPA, the solution was to use insertable = false in the column definition. 
    JPA will ignore then that column while inserting in the Database and the default value will be used.
    @Column(name = "myColumn", insertable = false)

    Spring AOP Around Advice 實作 Exception 處理

    緣由:專案內需要將Exception獨立抽出來處理,為了不影響原有的商業邏輯,並且讓code reuse
    所以第一時間就想到要用AOP實作,順便回去練一下很久沒碰的Spring AOP,並複習一下觀念
    問題:Exception處理
    解決方式:Spring AOP Around Advice
    好處:
    1. 統一錯誤訊息,讓每個工程師各寫各的錯誤處理風格可以得到統一。
    2. 讓其他人可以專注在商務邏輯
    3. 程式看起來比較簡潔乾淨
    基本上我不解釋觀念,因為網路上已經有很多很棒的解說了
    我也還在學習,很多東西其實第一次看完全都不懂,很抽象,
    但隨著時間、經驗的累積,又回去看了第二次第三次,就會越來越有感覺
    spring-aop-diagram.jpgspring-aop-diagram.jpg
    In Spring AOP, 4 type of advices are supported :
    • Before advice – Run before the method execution
    • After returning advice – Run after the method returns a result
    • After throwing advice – Run after the method throws an exception
    • Around advice – Run around the method execution, combine all three advices above.
    ============================= 分隔線 =================================
    我是使用 Around advice ,其實也就是把程式裡散落在各處的try catch集中至ExceptionAdvice統一處理。
    build.gradle
    apply plugin: 'java'
    apply plugin: 'eclipse'
    apply plugin: 'maven'
    
    compileJava.options.encoding = 'UTF-8'
    def springVersion = "3.2.6.RELEASE"
    
    dependencies {
        compile 'org.aspectj:aspectjweaver:1.7.1'
        compile 'org.slf4j:jcl-over-slf4j:1.7.1'
        compile 'org.slf4j:slf4j-log4j12:1.7.1'
        compile "org.springframework:spring-aop:$springVersion"
        compile "org.springframework:spring-context:$springVersion"
    }
    
    applicationContext.xml
    
    
        
    
        
        
        
        
            
                
                
            
         
    
    
    com.test.aop.advice.ExceptionAdvice
    public class ExceptionAdvice {
        private static Logger log = LoggerFactory.getLogger(ExceptionAdvice.class);
    
        public Object exceptionHandler(ProceedingJoinPoint proceedingJoinPoint) {
            Object value = null;
    
            try {
                value = proceedingJoinPoint.proceed();
            } catch (Throwable e) {
                log.info(proceedingJoinPoint.getSignature().getName() + " error");
                
                String errorMsg = "內部錯誤:" + e.getMessage();
                String errorCode = "500";
                
                Map resultJsonMap = new HashMap();
                resultJsonMap.put("successful", false);
                resultJsonMap.put("errorCode", errorCode);
                resultJsonMap.put("errorMsg", errorMsg );
    
                value = resultJsonMap;
                log.info(value.toString());
            }
            return value;
        }
    
    com.test.service.TestService
    public class TestService {
        private static ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        public String runTest() {
            throw new IllegalArgumentException("這是測試");
        }
    
        public static void main(String[] args) {
            TestService ts = ac.getBean("testService", TestService.class);
            ts.runTest();
        }
    }
    
    參考資料

    2015年3月4日 星期三

    Java ResourceBundle 多語系(本地化)

    http://villebez.logdown.com/posts/2014/07/25/java-resourcebundle

    這個類提供軟體國際化的捷徑。通過此類,可以使您所編寫的程式可以:
    輕鬆地當地語系化或翻譯成不同的語言
    一次處理多個語言環境
    以後可以輕鬆地進行修改,支援更多的語言環境
    這個類的作用就是讀取資源屬性檔(properties),然後根據.properties檔的名稱資訊(當地語系化資訊),匹配當前系統的國別語言資訊(也可以程式指定),然後獲取相應的properties檔的內容。
    使用這個類,要注意的一點是,這個properties檔的名字是有規範的:一般的命名規範是:自訂名_語言代碼_國別代碼.properties,如果是默認的,直接寫為:自訂名.properties
    例如:
    example.properties
    example_en_US.properties
    example_zh_TW.properties
    範例:
    定義資源檔,放到src的根目錄下面
    example_en_US.properties
    aaa = Hello
    
    example_zh_TW.properties
    aaa = \u54C8\u56C9
    
    public static void main(String[] args) {
             Locale locale1 = new Locale("zh", "TW"); 
         ResourceBundle resb1 = ResourceBundle.getBundle("example", locale1); 
         System.out.println(resb1.getString("aaa")); 
    
         Locale locale2 = new Locale("en", "US"); 
         ResourceBundle resb2 = ResourceBundle.getBundle("example", locale2); 
         System.out.println(resb2.getString("aaa")); 
    }
    
    執行結果:
    哈囉
    Hello
    
    Eclipse Plugin:ResourceBundleEditor
    好用的properties編輯工具,可以同時開啟不同語系的properties檔案,自動同步key,方便編輯多語系value,並會自動將文字轉換為Java Unicode Escape的格式

    Apache Thrift

    Command:thrift --gen java
    Example.thrift



    include "example2.thrift"
    namespace java com.thrift.example
    typedef i32 int  
    typedef i64 long
    
    service ThriftAuthService {  
        example2.XXX auth(1:string account, 2:string password),
    }

    2015年3月2日 星期一

    Gradle Build Project Example

    • Build.gradle : Simple Java Project Example

    apply plugin: 'java'
    sourceSets {
        main {
            java {
                srcDir 'src'
            }
            resources {
                srcDir 'src'
            }
        }
    }
    repositories {
        maven {
            credentials {
                username 'deployment'
                password ''
            }
            url "http://127.0.0.1:8081/nexus/content/groups/public/"
        }
    }
     
    dependencies {
        compile 'junit:junit:4.11'
        …
        …
    }
    

    • Build.gradle : Web Project Example

    apply plugin: 'eclipse-wtp'
    apply plugin: 'jetty'
    

    • Build.gradle : Application Project Example

    apply plugin: 'application'
    
    def createScript(project, mainClass, name) {
      project.tasks.create(name: name, type: CreateStartScripts) {
        outputDir       = new File(project.buildDir, 'scripts')
        mainClassName   = mainClass
        applicationName = name
        classpath       = project.tasks[JavaPlugin.JAR_TASK_NAME].outputs.files + project.configurations.runtime
    }
    
    project.tasks[name].dependsOn(project.jar)
    
      project.applicationDistribution.with {
        into("bin") {
          from(project.tasks[name])
          fileMode = 0755
        }
      }
      
    project.tasks[name].doLast {
        unixScript.text = unixScript.text.replace("\$CLASSPATH", ".:\$APP_HOME/lib/*") 
        //windowsScript.text = windowsScript.text.replace("%CLASSPATH%", ".;%APP_HOME%\\lib\\*") 
    }
    }
    
    startScripts.enabled = false
    run.enabled = false
    
    createScript(project, 'com.gigabyte.HelloWorld ', 'helloworld')

    2015年2月4日 星期三

    Gradle & Nexus

    Logdown -> http://villebez.logdown.com/posts/2015/01/27/gradle
    最近為了改善程式庫相依、專案建置、佈署效率與正確的版本控管,所以研究了 Gradle 自動化工具。
    另外,為了做部門的 Local Repository ,方便上傳、使用自行開發的 lib,所以建置了 Nexus 。
    關於Nexus的安裝啟用,官網 nexus-book 已經有很詳細的參考說明了,
    step by step就可以執行一個基本的Repository Server了。
    推薦qrtt1在Codedata發表一系列關於Gradle的文章,【認識 Gradle】
    從ant -> Maven -> Gradle,利用範例講解的很詳細。
    如果要了解專案相依管理,可以直接跳到這篇 【認識 Gradle】(7)Java 專案相依管理
    這篇並不是要介紹這兩個工具,
    只是個紀錄,紀錄用了Gradle遇到的問題與解決方式,所以請先對Gradle有初步的了解。
    這些問題可能也是大家剛開始使用常會遇到的,希望可以幫到你/妳。
    Q1: apply plugin 是什麼?? 有哪些可以使用
    A1.1: 類似於import, include,也就是 reuse logic
    A1.2: 請參考這裡,更進階可以自行客製Plugin
    Q2: 程式中文註解,造成編譯失敗
    A2: 請服用~ compileJava.options.encoding = 'UTF-8'
    Q3: 在MVNrepository找不到想要的libs
    A3: 幾個方法,1. 上傳到自行建置的Repository Server,2. include local jar file
    Q4: 什麼是providedCompile,跟compile有什麼差別
    A4: providedCompile也是編譯時,專案會用到的jar,但跟compile最大的差異在,宣告為providedCompile的jar file不會打包到war file,所以當我的專案需要用到tomcat-catalina libs時,如果將它宣告為compile,則war檔在tomcat server執行時會造成library conflict錯誤。
    Q5: 如何改變webapp dir
    A5: project.webAppDirName = 'WebContent'