2017年2月28日 星期二

三種啟動 Thread 的方法 (Thread 二)

Thread 有 8 個建構子,此篇使用到以下 4 個
Thread():預設建構子,名稱是 Thread-Number
Thread(String):給 Thread 名稱
Thread(Runnable):給Runnable 物件
Thread(Runnable, String):給Runnable 物件,並給 Thread 名稱


※Thread

public class ThreadTest1 extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
    
    public static void main(String... a) {
        ThreadTest1 t1 = new ThreadTest1();
        t1.start();
        Thread t2 = new Thread(t1);
        t2.start();
        Thread t3 = new Thread(t1, "xxx");
        t3.start();
    
        new Thread("xxx") {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
    
        }.start();
    }
}

※最後是匿名寫法



※Runnable

Runnable 是個介面,因為 Thread 是 class,如果自己寫的 class 已經繼承了某個類別,那 java 就不允許再繼承了,所以可以使用 Runnable


public class ThreadTest2 implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
    
    public static void main(String... a) {
        ThreadTest2 t1 = new ThreadTest2();
        // t1.start();
        Thread t2 = new Thread(t1);
        t2.start();
        Thread t3 = new Thread(t1, "xxx");
        t3.start();
    
        new Thread(t1, "xxx") {
            @Override
            public void run() {
                System.out.println("t1:" + Thread.currentThread().getName());
            }
        }.start();
    
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Runnable:" + Thread.currentThread().getName());
            }
        }, "ooo").start();
    
        // Java 8 的 lambda 寫法,這樣子 ThreadTest2 可以不用 implements 了
        new Thread(() -> System.out.println("t1:" + Thread.currentThread().getName()), "xxx").start();
    }
}

※最後兩個是匿名寫法

※Runnable 並沒有start(),所以註解打開會編譯錯誤



※Callable

此種方式是 java 1.5 增加的,實作 Runnable 要寫 run 方法;而實作 Callable 要寫 call 方法
call 有例外有返回值;run 都沒有


import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
    
public class ThreadTest3 implements Callable<String> {
    @Override
    public String call() throws Exception {
        return Thread.currentThread().getName();
    }
    
    public static void main(String... a) {
        ExecutorService service = Executors.newFixedThreadPool(1);
        Future<String> future = service.submit(new ThreadTest3());
    
        // Java 8 的 lambda 寫法,這樣子 ThreadTest3 可以不用 implements 了
        // Future<String> future = service.submit(() -> Thread.currentThread().getName());
    
        try {
            String s = future.get();
            System.out.println("s=" + s); // pool-1-thread-1
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    
        List<Runnable> list = service.shutdownNow();
        System.out.println(list.size());
//        service.shutdown();
    }
}





※Callable 的匿名寫法

public class ThreadTest3 {
    public static void main(String... a) {
        ExecutorService service = Executors.newFixedThreadPool(1);
        Future<String> future = service.submit(new Callable<String>() {
            @Override
            public String call() {
                return Thread.currentThread().getName();
            }
        });
    
        try {
            String s = future.get();
            System.out.println("s=" + s);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    
        List<Runnable> list = service.shutdownNow();
        System.out.println(list.size());
        // service.shutdown();
    }
}

※shutdown() 或 shutdownNow() 不寫也不會錯,但Eclipse裡的console,有個Terminate(正方形)會變成紅色的,表示未結束,所以要加這兩個其中之一



※shutdown() 和 shutdownNow() 的區別

shutdown 會執行完 Runnable 後才關閉
shutdownNow 會馬上關閉,還沒執行的 Runnable 以 List<Runnable> 傳回。

2017年2月27日 星期一

啟動 Thread 時的注意事項 (Thread 一)

※main方法也是Thread

public static void main(String... a) {
    System.out.println(Thread.currentThread().getName()); // main
    System.out.println("Thread數量=" + Thread.activeCount()); // 1
}




※Thread名稱

public class ThreadTest1 extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
    
    // public void start() {
    // System.out.println("Start method");
    // }
    
    public static void main(String... a) {
        new ThreadTest1().start();
        new ThreadTest1().run();
    }
}

※直接呼叫 run() 的Thread名稱是main;呼叫 start() 的 Thread 預設名稱是 Thread-0
其實是「Thread-」加數字,以上面的例子,如果將 main 裡的 start() 和 run() 互換,
就會變成 main 和 Thread-1,因為它知道有 main Thread 了

※如果不喜歡Thread-數字的名稱,可以用如下的方法修改
ThreadTest1 t1 = new ThreadTest1();
t1.setName("xxx");
t1.start();
這樣子名稱就變成xxx了

※註解的 start() 打開後,main 的start() 就不會呼叫 run()了,因為Thread 的 start() 方法是
public synchronized void start()
所以變成覆寫,當然參數不同沒有關係
而如果將覆寫的回傳值改成其他的也會編譯錯誤

※start() 只能呼叫一次,超過會出「java.lang.IllegalThreadStateException」的錯



※Thread.activeCount只是估計值

public class ThreadTest1 extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
    
    public static void main(String... a) {
        new ThreadTest1().start();
        new ThreadTest1().start();
        new ThreadTest1().run();
        new ThreadTest1().run();
        System.out.println("Thread數量=" + Thread.activeCount());
    }
}

※Thread.activeCount()不一定會顯示正確的結果,如start()才是真正的Thread;而呼叫run()就不是,所以以這個例子是一個main Thread + 2個Start(),所以應該是3個
但多執行幾次,數字有可能變成2,甚至是1
因為run()方法裡一下子就執行完了,執行完了Thread 也就消失了,所以start寫在Thread.acdtiveCount() 的上一行
如果寫在 run() 方法裡也是會有類似的情形



※ run 和 start的不同

public class ThreadTest1 extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName + "執行了" + i + "次");
        }
    }
    
    public static void main(String... a) {
        // new ThreadTest1().start();
        // new ThreadTest1().start();
        new ThreadTest1().run();
        new ThreadTest1().run();
    }
}

※結果:
main執行了1次
main執行了2次
main執行了3次
...
main執行了100次
main執行了1次
main執行了2次
main執行了3次
...
main執行了100次

※如果將 start() 註解打開, run() 註解,會得到類似以下的結果
...
Thread-0執行了21次
Thread-1執行了1次
Thread-0執行了22次
Thread-1執行了2次
Thread-0執行了23次
Thread-1執行了3次
Thread-1執行了4次
Thread-1執行了5次
...

這才是正確的結果,Thread 要互相交互



※無限迴圈

public class ThreadTest extends Thread {
    @Override
    public void run() {
        int i = 1;
        for (;;) {
            System.out.println(i);
            ++i;
        }
    }
    
    public static void main(String... a) {
        Thread t = new Thread(new ThreadTest());
        t.setDaemon(true);
        t.start();
    
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

※如果不使用 setDaemon(true),將會無限迴圈
但如果使用 setDaemon(true),可以讓 main 執行完時,呼叫setDaemon(true) 的 Thread 也結束
一定要在 start() 之前呼叫


2017年2月24日 星期五

變壓器 (Adapter) 模式

就好像是變壓器一樣,能將110變220
如兩個物件都不同,但用中間的轉換器可以達到互通的目的
1.寫兩組介面和實作,彼此無關聯
2.寫轉換器,繼承其中一個實作並實作另一個介面
測試時,取得介面的方法就可取到實作的內容


public interface Adapter1 {
    String getOoo();
    String getXxx();
}
--------------------
public class Adapter1Impl implements Adapter1 {
    @Override
    public String getOoo() {
        return "ooo";
    }
    
    @Override
    public String getXxx() {
        return "xxx";
    }
}





public interface Adapter2 {
    String getAaa();
    String getBbb();
}
--------------------
public class Adapter2Impl implements Adapter2 {
    @Override
    public String getAaa() {
        return "aaa";
    }
    
    @Override
    public String getBbb() {
        return "bbb";
    }
}





public class Center extends Adapter2Impl implements Adapter1 {
    String a = super.getAaa();
    String b = super.getBbb();
    
    @Override
    public String getOoo() {
        return a;
    }
    
    @Override
    public String getXxx() {
        return b;
    }
}




※測試

Adapter1 a1 = new Center();
System.out.println(a1.getOoo());
System.out.println(a1.getXxx());

※結果:
aaa
bbb

2017年2月23日 星期四

策略模式

分成兩個部分
1.介面寫個方法,然後寫類別實作
2.寫個類別,將1的介面為他的 field,並寫一支方法,裡面寫呼叫介面裡的方法



public interface Strategy {
    void method();
}
--------------------
public class StrategySon1 implements Strategy {
    @Override
    public void method() {
        System.out.println("StraterySon1 的 someMethod");
    }
}
--------------------
public class StrategySon2 implements Strategy {
    @Override
    public void method() {
        System.out.println("StraterySon2 的 someMethod");
    }
}




public class Context {
    private Strategy strategy;
    
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }
    
    public void other() {
        strategy.method();
    }
}




※測試

Context ctn = new Context(new StrategySon1());
ctn.other();
    
new Context(new StrategySon2()).other();

※結果:
StraterySon1 的 someMethod
StraterySon2 的 someMethod



※使用匿名和 lambda

Xxx x1 = new Xxx(new Strategy(){
    @Override
    public void method(){
        System.out.println("strategy1");
    }
});
x1.m();
    
Xxx x2 = new Xxx(() -> System.out.println("strategy2"));
x2.m();

※還可以用匿名和 lambda,這樣 Impl 的 class 都不用寫了,也可以將他寫成共用方法

2017年2月21日 星期二

代理模式

自己可以去買東西,但也可以叫人家買,叫人家買就是一種代理


※自己類別

public interface Self {
    public void buyChair();
    public void buyTable();
}
--------------------
public class SelfImpl implements Self {
    private String buyMan = "自己";
    
    SelfImpl(String buyMan) {
        this.buyMan = buyMan;
    }
    
    @Override
    public void buyChair() {
        System.out.println(buyMan + "買椅子");
    }
    
    @Override
    public void buyTable() {
        System.out.println(buyMan + "買桌子");
    }
}




※代理類別

public class Proxy implements Self {
    private Self proxyMan;
    
    Proxy(Self proxyMan) {
        this.proxyMan = proxyMan;
    }
    
    @Override
    public void buyChair() {
        proxyMan.buyChair();
    }
    
    @Override
    public void buyTable() {
        proxyMan.buyTable();
    }
}




※測試

Self self = new SelfImpl("bruce");
self.buyChair();
self.buyTable();
System.out.println();
Self proxy = new Proxy(new SelfImpl("bruce"));
proxy.buyChair();
proxy.buyTable();

※前三行不用代理;後三行使用代理

2017年2月20日 星期一

建造者、生成器(Builder)模式

模板模式如果順序想讓呼叫端自己決定,可加個List

有四個名詞需了解
Builder:為創建具體產品的具體建造者提供介面
ConcreteBuilder:建造具體產品
Director:呼叫 Builder 介面來創建產品物件
Product:具體產品(此例為模板模式的程式碼)

創建兩個抽象類別(builder類別和product類別),並讓子類實作,其中builder和product產生關聯
最後 Director 放 builder


public abstract class AbstractTemplate {
    public enum EnumMethods {
        m1, m2, m3;
    }
    
    private List<EnumMethods> list = new ArrayList<>();
    
    public void setList(List<EnumMethods> list) {
        this.list = list;
    }
    
    protected abstract void method1();
    protected abstract void method2();
    protected abstract void method3();
    
    public void builderMethod() {
        for (EnumMethods em : list) {
            switch (em) {
            case m1:
                this.method1();
                break;
            case m2:
                this.method2();
                break;
            case m3:
                this.method3();
                break;
            }
        }
    }
}
--------------------
public class Concrete1 extends AbstractTemplate {
    @Override
    protected void method1() {
        System.out.println("Concrete1 m1");
    }
    
    @Override
    protected void method2() {
        System.out.println("Concrete1 m2");
    }
    
    @Override
    protected void method3() {
        System.out.println("Concrete1 m3");
    }
}
--------------------
public class Concrete2 extends AbstractTemplate {
    @Override
    protected void method1() {
        System.out.println("Concrete2 m1");
    }
    
    @Override
    protected void method2() {
        System.out.println("Concrete2 m2");
    }
    
    @Override
    protected void method3() {
        System.out.println("Concrete2 m3");
    }
}




※測試

List<EnumMethods> list1 = new ArrayList<>();
list1.add(EnumMethods.m2);
list1.add(EnumMethods.m1);
list1.add(EnumMethods.m3);
    
List<EnumMethods> list2 = new ArrayList<>();
list2.add(EnumMethods.m3);
list2.add(EnumMethods.m2);
list2.add(EnumMethods.m1);
    
AbstractTemplate c1 = new Concrete1();
c1.setList(list1);
c1.builderMethod();
System.out.println();
AbstractTemplate c2 = new Concrete2();
c2.setList(list2);
c2.builderMethod();

※結果:
Concrete1 m2
Concrete1 m1
Concrete1 m3

Concrete2 m3
Concrete2 m2
Concrete2 m1



加上Builder


public abstract class AbstractBuilder {
    public abstract void setList(List<EnumMethods> list);
    public abstract AbstractTemplate getAbstractTemplate();
}
--------------------
public class Concrete1Builder extends AbstractBuilder {
    private Concrete1 c1 = new Concrete1();
    
    @Override
    public void setList(List<EnumMethods> list) {
        c1.setList(list);
    }
    
    @Override
    public AbstractTemplate getAbstractTemplate() {
        return c1;
    }
}
--------------------
public class Concrete2Builder extends AbstractBuilder {
    private Concrete2 c2 = new Concrete2();
    
    @Override
    public void setList(List<EnumMethods> list) {
        c2.setList(list);
    }
    
    @Override
    public AbstractTemplate getAbstractTemplate() {
        return c2;
    }
}




※測試

List<EnumMethods> list1 = new ArrayList<>();
list1.add(EnumMethods.m2);
list1.add(EnumMethods.m1);
list1.add(EnumMethods.m3);
    
List<EnumMethods> list2 = new ArrayList<>();
list2.add(EnumMethods.m3);
list2.add(EnumMethods.m2);
list2.add(EnumMethods.m1);
    
AbstractBuilder c1 = new Concrete1Builder();
c1.setList(list1);
AbstractTemplate at1 = c1.getAbstractTemplate();
at1.builderMethod();
System.out.println();
AbstractBuilder c2 = new Concrete1Builder();
c2.setList(list2);
AbstractTemplate at2 = c2.getAbstractTemplate();
at2.builderMethod();

※結果一樣


加上Director


public class Director {
    private List<EnumMethods> list1 = new ArrayList<>();
    private List<EnumMethods> list2 = new ArrayList<>();
    Concrete1Builder c1 = new Concrete1Builder();
    Concrete2Builder c2 = new Concrete2Builder();
    
    public void setList1(List<EnumMethods> list1) {
        this.list1 = list1;
    }
    
    public void setList2(List<EnumMethods> list2) {
        this.list2 = list2;
    }
    
    public Concrete1 getConcrete1() {
        c1.setList(list1);
        return (Concrete1) c1.getAbstractTemplate();
    }
    
    public Concrete2 getConcrete2() {
        c2.setList(list2);
        return (Concrete2) c2.getAbstractTemplate();
    }
}




※測試

List<EnumMethods> list1 = new ArrayList<>();
list1.add(EnumMethods.m2);
list1.add(EnumMethods.m1);
list1.add(EnumMethods.m3);
    
List<EnumMethods> list2 = new ArrayList<>();
list2.add(EnumMethods.m3);
list2.add(EnumMethods.m2);
list2.add(EnumMethods.m1);
    
Director dir = new Director();
dir.setList1(list1);
dir.setList2(list2);
    
dir.getConcrete1().builderMethod();
System.out.println();
dir.getConcrete2().builderMethod();

※結果一樣

2017年2月19日 星期日

模板 (Template) 模式

抽象父類別定義多個方法給子類實作,而最關鍵的是抽象父類別還有一支呼叫其他方法的方法,也就是將需要呼叫的方法,集中在一個方法裡


※父/子類別

public abstract class AbstractTemplate {
    protected abstract void method1();
    protected abstract void method2();
    protected abstract void method3();
    
    public void templateMethod() {
        this.method1();
        this.method2();
        this.method3();
    }
}
--------------------
public class Concrete1 extends AbstractTemplate {
    @Override
    protected void method1() {
        System.out.println("Concrete1 m1");
    }
    
    @Override
    protected void method2() {
        System.out.println("Concrete1 m2");
    }
    
    @Override
    protected void method3() {
        System.out.println("Concrete1 m3");
    }
}
--------------------
public class Concrete2 extends AbstractTemplate {
    @Override
    protected void method1() {
        System.out.println("Concrete2 m1");
    }
    
    @Override
    protected void method2() {
        System.out.println("Concrete2 m2");
    }
    
    @Override
    protected void method3() {
        System.out.println("Concrete2 m3");
    }
}




※測試

AbstractTemplate c1 = new Concrete1();
AbstractTemplate c2 = new Concrete2();
c1.templateMethod();
System.out.println();
c2.templateMethod();

※結果:
Concrete1 m1
Concrete1 m2
Concrete1 m3

Concrete2 m1
Concrete2 m2
Concrete2 m3

2017年2月18日 星期六

抽象工廠模式

工廠方法模式就是有一個工廠,裡面放工廠要用的方法,如果有多個工廠,就可以使用抽象工廠模式,下面分成兩個部分,第二個部分就是將每一個工廠變成一個產品

提供一系列相關或相互依賴的介面,不用指定他們的具體類別

分成兩個部分
1.產品:寫產品類別後,讓子類繼承
以下寫兩個產品,並寫4個子類別,其中2個子類別繼承第一個;另外2個子類別繼承第二個

2.工廠:工廠裡寫回傳1的物件,然後也是讓子類別實作


※產品

public abstract class AbstractProductXXX {
    public void sameMethod() {
        System.out.println("抽象產品XXX共有的方法");
    }
    
    public abstract void doSomething();
}
--------------------
public abstract class AbstractProductOOO {
    public void sameMethod() {
        System.out.println("抽象產品OOO共有的方法");
    }
    
    public abstract void doSomething();
}
========================================
public class ProductA extends AbstractProductXXX {
    @Override
    public void doSomething() {
        System.out.println("產品A實現抽象產品1的方法");
    }
}
--------------------
public class ProductB extends AbstractProductXXX {
    @Override
    public void doSomething() {
        System.out.println("產品B實現抽象產品1的方法");
    }
}
--------------------
public class ProductC extends AbstractProductOOO {
    @Override
    public void doSomething() {
        System.out.println("產品C實現抽象產品2的方法");
    }
}
--------------------
public class ProductD extends AbstractProductOOO {
    @Override
    public void doSomething() {
        System.out.println("產品D實現抽象產品2的方法");
    }
}




※工廠

public abstract class AbstractFactory {
    public abstract AbstractProductXXX getProductXXX();
    
    public abstract AbstractProductOOO getProductOOO();
}
--------------------
public class BreadFactory extends AbstractFactory {
    @Override
    public AbstractProductXXX getProductXXX() {
        return new ProductA();
    }
    
    @Override
    public AbstractProductOOO getProductOOO() {
        return new ProductC();
    }
}
--------------------
public class GrapeFactory extends AbstractFactory {
    @Override
    public AbstractProductXXX getProductXXX() {
        return new ProductB();
    }
    
    @Override
    public AbstractProductOOO getProductOOO() {
        return new ProductD();
    }
}




※測試

AbstractFactory bf = new BreadFactory();
AbstractProductXXX bf1 = bf.getProductXXX();
AbstractProductOOO bf2 = bf.getProductOOO();
bf1.sameMethod();
bf1.doSomething();
System.out.println();
bf2.sameMethod();
bf2.doSomething();
System.out.println();
    
AbstractFactory gf = new GrapeFactory();
AbstractProductXXX gf1 = gf.getProductXXX();
AbstractProductOOO gf2 = gf.getProductOOO();
gf1.sameMethod();
gf1.doSomething();
System.out.println();
gf2.sameMethod();
gf2.doSomething();

※結果:
抽象產品XXX共有的方法
產品A實現抽象產品1的方法

抽象產品OOO共有的方法
產品C實現抽象產品2的方法

抽象產品XXX共有的方法
產品B實現抽象產品1的方法

抽象產品OOO共有的方法
產品D實現抽象產品2的方法



※優缺點

優點是不需要知道裡面是如何實作的;缺點是要新增產品時,要改的地方很多

2017年2月17日 星期五

工廠方法模式

分成兩部分
1.工廠:寫一個介面,然後定義一些方法,最後由多個子類實作
2.產生工廠:寫一個抽象類別,使它可以產生1的產品,也是由子類別實作
使一個類別的實體化可以延遲到子類

※第二部分的產生工廠,如不寫抽象類別,然後將子類別的方法改成static,
因為變簡單了,所以就變成了簡單工廠模式,或者說靜態工廠模式


※1.工廠

public interface BreadFactory {
    void getBread();
    
    void getRaisin();
}
--------------------
public class FranceBread implements BreadFactory {
    @Override
    public void getBread() {
        System.out.print("法國麵包");
    }
    
    @Override
    public void getRaisin() {
        System.out.println("不用葡萄乾");
    }
}
--------------------
public class BoomBread implements BreadFactory {
    @Override
    public void getBread() {
        System.out.print("炸彈麵包");
    }
    
    @Override
    public void getRaisin() {
        System.out.println("取得葡萄乾");
    }
}




※2.產生工廠

public abstract class AbstractBreadFactory {
    public abstract <T extends BreadFactory> T generateBread(Class<T> clazz);
}
--------------------
public class MadeBreadFactory extends AbstractBreadFactory {
    @SuppressWarnings("unchecked")
    @Override
    public <T extends BreadFactory> T generateBread(Class<T> clazz) {
        BreadFactory breadFactory = null;
        try {
            breadFactory = (T) Class.forName(clazz.getName()).newInstance();
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) breadFactory;
    }
}




※測試

AbstractBreadFactory factory = new MadeBreadFactory();
    
BreadFactory fb = factory.generateBread(FranceBread.class);
fb.getBread();
fb.getRaisin();
    
BreadFactory bb = factory.generateBread(BoomBread.class);
bb.getBread();
bb.getRaisin();

※結果:
法國麵包不用葡萄乾
炸彈麵包取得葡萄乾



※好處

只要知道類別名稱或字串(因Class.format也可接收包.類名的字串)即可,不用知道創建的過程,也就是低耦合

擴展性也很好,如再增加一個鳳梨麵包,只要增加一個類別即可,其他都不用改

使用JDBC時只要將Class.forName的字串改掉即可切換就是一例,但SQL當然要用標準的才行

2017年2月15日 星期三

ng-hide、ng-show、ng-disabled、ng-readonly、ng-selected、ng-checked (angularJS 六)

※ng-hide、ng-show、ng-disabled、ng-readonly 

※寫死的值

<html>
    <script type="text/javascript" src="angular.js"></script>
    
    <body ng-app>
        <p ng-hide="true">看不見</p>
        <p ng-hide="false">看見</p>
    
        <p ng-show="true">看見</p>
        <p ng-show="false">看不見</p>
    
        <p>
            <button ng-disabled="true">按不下去</button>
            <button ng-disabled="false">按的下去</button>
        </p>
    
        <p>
            <input ng-readonly="true" value="不可改" />
            <input ng-readonly="false" value="可改" />
        </p>
    </body>
</html>v

※注意 readonly 屬性在HTML裡有三種方式:readonly="true"、readonly、readonly="readonly"
但用ng-readonly就只有true|false;disabled也是一樣

※初始值

<html>
    <script type="text/javascript" src="angular.js"></script>
    
    <body ng-app ng-init="xxx=true; ooo=10">
        <p ng-hide="xxx">看不見</p>
    
        <p ng-show="xxx">看見</p>
    
        <p>
            <button ng-disabled="xxx">按不下去</button>
        </p>
    
        <p>
            <input ng-readonly="ooo > 1" value="不可改" />
        </p>
    </body>
</html>

※變數也可以取名為readonly,但並不表示 ng-readonly="readonly" 成立,只是剛好 readonly 是個true|false

※動態給值

<html>
    <script type="text/javascript" src="angular.js"></script>
    
    <body ng-app ng-init="xxx=true">
        <p ng-hide="xxx">看不見</p>
        <p ng-show="xxx">看見</p>
    
        <input type="checkbox" ng-model="xxx">按我
        <p>{{ xxx }}</p>
    </body>
</html>





※ng-selected、ng-checked

<html>
    <script type="text/javascript" src="angular.js"></script>
    
    <body ng-app>
        <select>
            <option value="a">A</option>
            <option value="b" ng-selected="true">B</option>
            <option value="c">C</option>
        </select>
        <br />
        <select multiple>
            <option value="a">A</option>
            <option value="b" ng-selected="true">B</option>
            <option value="c" ng-selected="true">C</option>
        </select>
        <br />
        <input type="checkbox" name="xxx" />c1
        <input type="checkbox" name="xxx" ng-checked="true" />c2
        <input type="checkbox" name="xxx" ng-checked="true" />c3
        <br />
        <input type="radio" name="ooo" />r1
        <input type="radio" name="ooo" ng-checked="true" />r2
        <input type="radio" name="ooo" />r3
    </body>
</html>

※觀念和上面一模一樣

2017年2月14日 星期二

ng-options、$even、$odd、$index (angularJS 五)

※ng-options 和 ng-repeat 不同

<html>
    <script type="text/javascript" src="angular.min.js"></script>
    
    <body ng-app='xxx' ng-controller='ccc'>
        <select ng-model="sel">
            <option ng-repeat="l in lists" value="{{l.x}}">{{l.o}}</option>
        </select>
        <p>選到的value是{{sel}}</p>
        
        <select ng-model="sel2" ng-options="l.o for l in lists"></select>
        <p>選了{{sel2.o}},value是{{sel2.x}}</p>
    </body>
</html>
    
<script>
    var app = angular.module('xxx', []);
    app.controller('ccc', ($scope) => {
        $scope.lists = [
            {
                o: 'a', x: 1
            }, {
                o: 'b', x: 2
            }, {
                o: 'c', x: 3
            }
        ];
    });
</script>

※ng-repeat by 字串;ng-options by 物件



※ng-options 可設多個物件

<html>
    <script type="text/javascript" src="angular.min.js"></script>
    
    <body ng-app='xxx' ng-controller='ccc'>
        <select ng-model="sel" ng-options=" p2.name for (p1, p2) in lists "></select>
        <p>選了{{sel.name}},價錢是{{sel.price}},製造年是{{sel.date}}年</p>
    </body>
</html>
    
<script>
    var app = angular.module('xxx', []);
    app.controller('ccc', ($scope) => {
        $scope.lists = {
            chessProduct1: {name:'象棋', price: 30, date: '1999'},
            chessProduct2: {name:'五子棋', price: 25, date: '2000'},
            chessProduct3: {name:'圍棋', price: 40, date: '2010'}
        };
    });
</script>

※注意chessProduct1~3,這三個變數如果一樣會覆蓋,使畫面上只剩最後一個



※$even、$odd、$index

<html>
    <script type="text/javascript" src="angular.min.js"></script>
    
    <body ng-app='xxx' ng-controller='ccc'>
        <table>
            <tr ng-repeat="l in lists |orderBy:'name'">
                <td ng-if="$odd" style="background-color:lightgreen">{{ $index + 1 }}</td>
                <td ng-if="$even">{{ l.name }}</td>
                <td>{{ l.price }}</td>
            </tr>
        </table>
    </body>
</html>
    
<script>
    var app = angular.module('xxx', []);
    app.controller('ccc', ($scope) => {
        $scope.lists = [
            {name: 'papaya', price: 30}, 
            {name: 'apple', price: 25}, 
            {name: 'guava', price: 80},
            {name: 'durian', price: 60},
            {name: 'banana', price: 40}
        ];
    });
</script>

※這三個都是從0開始的
$index:從0開始的數字
$odd:奇數時會顯示
$even:偶數時會顯示

2017年2月13日 星期一

Service (angularJS 四)

官網API連結

※$location、$http、$timeout、$interval

<html>
    <script type="text/javascript" src="angular.js"></script>
    
    <body ng-app='xxx'>
        <div ng-controller='ooo'>
            <p>{{myUrl}}</p>
            <p>{{myHttp}}</p>
            <p>{{myURL}}</p>
            <p>{{myTimeout}}</p>
            <p>{{myInterval}}</p>
        </div>
    </body>
</html>
    
<script>
    var app = angular.module('xxx', []);
    app.controller('ooo', function($scope, $location, $http, $timeout, $interval) {
        $scope.myUrl = $location.absUrl();
    
        $http.get("http://localhost:8080/TestServletXXX/xxx.jsp").then(function (response) {
            $scope.myHttp = response.data;
            $scope.myURL = response.config.url;
        });
    
        $timeout(function () {
            $scope.myTimeout = "我佇這,你看啥貨?";
        }, 2000);
    
        $interval(function () {
            $scope.myInterval = new Date().toLocaleTimeString();
        }, 1000);
    });
</script>

※$location:類似window.location

※$http:連到已啟動的伺服器,但Chrome會有同源策略的問題,可參考這篇

※$timeout:js的window.timeout,過幾毫秒做什麼事

※$interval:js的window.interval,每過幾毫秒做什麼事

※以上可以加debugger看還有什麼可以「.」的


※service

<html>
    <script type="text/javascript" src="angular.js"></script>
    
    <body ng-app='xxx'>
        <div ng-controller='ooo'>
            <p>{{self}}</p>
        </div>
    </body>
</html>
    
<script>
    var app = angular.module('xxx', []);
    app.controller('ooo', function($scope, zzz) {
        $scope.self = zzz.yyyFun(100);
    });
    
    app.service('zzz', function() {
        this.yyyFun = function (x) {
            return x + x;
        }
    });
</script>

※自定 service 的功能,也就是定義controller裡可以放的service,此例是zzz



※filter 抓 service 的方法

<html>
    <script type="text/javascript" src="angular.js"></script>
    
    <body ng-app='xxx'>
        <ul ng-controller='ooo'>
            <li ng-repeat="a in intArr">{{a | myFilter}}</li>
        </ul>
    </body>
</html>
    
<script>
    var app = angular.module('xxx', []);
    app.controller('ooo', ($scope) => {
        $scope.intArr = [73, 108, 49];
    });
    
    app.filter('myFilter',['zzz', (f) => { // 這裡的zzz對應到service,使用裡面的方法
        return (x) => {
            return f.yyy(x);
        };
    }]);
    
    app.service('zzz', function() {
        this.yyy = (x) => {
            return String.fromCharCode(x);
        }
    });
</script>

※zzz 對應好即可



※Servlet 回傳 JSON

@WebServlet(urlPatterns = { "/xxx" })
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String json = "{\"A\":\"1\",\"B\":2,\"C\":3.3}";
        System.out.println("json=" + json);
    
    //    JSONObject json = new JSONObject();
    //    json.put("A", "1");
    //    json.put("B", 2);
    //    json.put("C", 3.3);
    //    System.out.println("json=" + json.toString());
    
        resp.setContentType("application/json");
        resp.setCharacterEncoding("UTF-8");
    
        PrintWriter out = resp.getWriter();
        out.write(json);
        out.flush();
        out.close();
    }
}

※一定要用「"」,單引號我試的結果,前端會跑到fail,所以最好是用註解這一類的工具,才不會看到目睭拖窗

※JSON回傳「"xxx":["A":1,"B":2,"C":3]」,試的結果也是會跑到fail,很奇怪

※不使用setContentType也是可以的


※前端

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false"%>
<!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>
        <script type="text/javascript" src="angular.min.js"></script>
        <script>
            var app = angular.module('xxx', []);
            app.controller('ooo', function($scope, $http) {
                $http({
                    method : 'GET',
                    url : 'xxx'
                }).then(function successCallback(resp) {
                    $scope.a = resp.data.A;
                    $scope.b = resp.data.B;
                    $scope.c = resp.data.C;
                }, function errorCallback(resp) {
                    alert('fail');
                });
            });
        </script>
    </head>
    
    <body ng-app='xxx'>
        <div ng-controller='ooo'>
            <p>{{a}}</p>
            <p>{{b}}</p>
            <p>{{c}}</p>
        </div>
    </body>
</html>

※一載入頁面就呼叫了

※resp.data 是固定的,而後面如果是JSON還可以繼續「.」

2017年2月12日 星期日

單例模式

一個class只有一個實體


※餓漢式單例

public class Singleton {
    private static final Singleton SINGLETON = new Singleton();
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        return SINGLETON;
    }
}

※類別載入就創建物件,執行效率高,但浪費記憶體



※懶漢式單例

public class Singleton {
    private static Singleton singleton = null;
    
    private Singleton() {}
    
    public static synchronized Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

※第一次請求實體才會創建物件,但必須要用synchronized

※如果不用 synchronized 有可能會有多個實體,因為Parallel程序可能會進入,如下:
public class Singleton {
    private static Singleton singleton = null;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (singleton == null) {
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            singleton = new Singleton();
        }
        return singleton;
    }
}
    
    
    
public class MyThread implements Runnable {
    @Override
    public void run() {
        System.out.println(Singleton.getInstance());
    }
    
    public static void main(String... ss) {
        /*Runnable my = () -> {
            System.out.println(Singleton.getInstance());
        };*/
    
        MyThread my = new MyThread();
        for(int i=1; i<=5; i++){
            new Thread(my).start();
        }
    }
}

※停一秒鐘,然後 Parallel,就有可能會有2個實體

※註解是 Java8 的 lambda 寫法,此時可以不用 implements Runnable 和實作

※1.設定 msconfig
2.設定 taskmgr,針對java、javaw、Eclipse 使用一顆 CPU,還是一樣的結果,不知道為什麼
理論上單核是不會有併行的


※登記式單例

public class Singleton {
    private Singleton() {}
    
    public static Singleton getInstance() {
        return InnerSingleton.SINGLETON;
    }
    
    private static class InnerSingleton {
        private static final Singleton SINGLETON = new Singleton();
    }
}

※綜合餓漢和懶漢的最佳單例

2017年2月11日 星期六

DOM4j

※xml.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>top1
    top2
    <first fa="f1" fb="1f">
        first-1
        <second1 sa="s1">aaa</second1>
        <second2>bbb</second2>
        <second3>ccc</second3>
    </first>
    top3
    <first fa="f2" fb="2f">
        first-2
        <second1 sa="s2">ddd</second1>
        <second2>eee</second2>
        <second3>fff</second3>
    </first>
    top4
    <first fa="f3" fb="3f">
        first-3
        <second1 sa="s3">ggg</second1>
        <second2>hhh</second2>
        <second3>iii</second3>
    </first>
</root>





※maven

<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>


※讀檔

import java.util.Iterator;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
    
public class DOM4jTest {
    public static void main(String[] args) throws DocumentException {
        SAXReader reader = new SAXReader();
        Document doc = reader.read("src/main/java/xml.xml");
        Element root = doc.getRootElement();
    
        System.out.println("方法一");
        List<Element> first = root.elements();
        for (Element e : first) {
            System.out.println(e.getText().trim());
            for (Object o : e.attributes()) {
                System.out.println(((Attribute) o).getValue());
            }
    
            System.out.println("子元素");
            List<Element> second = e.elements();
            for (Element s : second) {
                System.out.println(s.getText().trim());
            }
            System.out.println(System.getProperty("line.separator"));
        }
    
        System.out.println("方法二");
        Iterator<Element> it2 = root.elementIterator();
        while (it2.hasNext()) {
            Element firstTwo = (Element) it2.next();
            // ...
        }
    
        System.out.println("方法三");
        for (Iterator<Element> it3 = root.elementIterator(); it3.hasNext();) {
            Element firstThree = it3.next();
            // ...
        }
    }
}

※方法二和三,迴圈裡的內容和方法一一樣



※使用XPath


※要使用 XPath 必需要有 jaxen 的 jar,否則執行selectSingleNode方法時會報錯
<dependency>
    <groupId>jaxen</groupId>
    <artifactId>jaxen</artifactId>
    <version>1.1.6</version>
</dependency>




import java.io.IOException;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.dom4j.tree.DefaultAttribute;
    
public class DOM4jTest {
    public static void main(String[] args) throws IOException, DocumentException {
        SAXReader reader = new SAXReader();
        Document doc = reader.read("src/main/java/xml.xml");
        Node root = doc.selectSingleNode("/root");
        List<Element> second1 = root.selectNodes("first/second1");
    
        for (Element e : second1) {
            System.out.println(e.getName());
            System.out.println(e.getText());
            System.out.println(e.attributeValue("sa"));
            System.out.println("---------------");
        }
    
        System.out.println("===============");
        List<Element> first = root.selectNodes("first");
        for (Element e : first) {
            System.out.println(e.getName());
            System.out.println(e.getText().trim());
    
            for (Object o : e.attributes()) {
                DefaultAttribute ele = (DefaultAttribute) o;
                System.out.println(ele.getStringValue());
            }
            System.out.println("===============");
        }
    }
}

※selectSingleNode 和 selectNodes 可以寫XPath



※寫檔

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
    
public class DOM4jTest {
    public static void main(String[] args) throws IOException {
        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement("root");
        Element first = root.addElement("first");
        Element second1 = first.addElement("second1");
        Element second2 = first.addElement("second2");
        Element second3 = first.addElement("second3");
    
        root.setText("top1" + System.getProperty("line.separator") + "\ttop2");
        first.setText("first-1");
        second1.setText("aaa");
        second2.setText("bbb");
        second3.setText("ccc");
    
        first.addAttribute("fa", "f1");
        first.addAttribute("fb", "1f");
        second1.addAttribute("sa", "s1");
    
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("UTF-8");
    
        File file = new File("D:/" + File.separator + "xml.xml");
        OutputStream fout = new FileOutputStream(file, true);
        XMLWriter out = new XMLWriter(fout, format);
        out.write(doc);
        out.close();
        System.out.println("XML已生成");
    }
}

※此例只是寫其中一個first而已

※變數format是讓產生出的XML有排版


JDOM

※xml.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>top1
    top2
    <first fa="f1" fb="1f">
        first-1
        <second1 sa="s1">aaa</second1>
        <second2>bbb</second2>
        <second3>ccc</second3>
    </first>
    top3
    <first fa="f2" fb="2f">
        first-2
        <second1 sa="s2">ddd</second1>
        <second2>eee</second2>
        <second3>fff</second3>
    </first>
    top4
    <first fa="f3" fb="3f">
        first-3
        <second1 sa="s3">ggg</second1>
        <second2>hhh</second2>
        <second3>iii</second3>
    </first>
</root>




※maven

<dependency>
    <groupId>jdom</groupId>
    <artifactId>jdom</artifactId>
    <version>1.1</version>
</dependency>




※讀寫

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
    
public class JDOMTest {
    public static void main(String[] args) throws JDOMException, IOException {
        write();
        read();
    }
    
    private static void read() throws IOException, JDOMException {
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build("src/main/java/xml.xml");
    
        Element root = doc.getRootElement();
        List<Element> list = root.getChildren();
        System.out.println(list.size());
        for (Element e : list) {
            System.out.println("===== 取元素和屬性 =====");
            System.out.println(e.getText().trim());
            List<Attribute> attrs = e.getAttributes();
            for (Attribute a : attrs) {
                System.out.println(a.getValue());
            }
            System.out.println("===== 取子元素和屬性 =====");
            System.out.println(e.getChildText("second1"));
            System.out.println(e.getChild("second1").getAttribute("sa").getValue());
            System.out.println(System.getProperty("line.separator"));
        }
    }
    
    private static void write() throws IOException {
        Element root = new Element("root");
        Element first = new Element("first");
        Element second1 = new Element("second1");
        Element second2 = new Element("second2");
        Element second3 = new Element("second3");
    
        root.setText("top1" + System.getProperty("line.separator") + "top2");
        first.setText("first-1");
        second1.setText("aaa");
        second2.setText("bbb");
        second3.setText("ccc");
    
        first.setAttribute("fa", "f1");
        first.setAttribute("fb", "1f");
        second1.setAttribute(new Attribute("sa", "s1"));
    
        root.addContent(first);
        first.addContent(second1);
        first.addContent(second2);
        first.addContent(second3);
    
        Document doc = new Document(root);
    
        File file = new File("D:/" + File.separator + "xml.xml");
        OutputStream fout = new FileOutputStream(file, true);
    
        XMLOutputter out = new XMLOutputter();
        out.setFormat(out.getFormat().setEncoding("UTF-8"));
        out.output(doc, fout);
        System.out.println("XML已生成");
    }
}




SAXParserFactory

※xml.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>top1
    top2
    <first fa="f1" fb="1f">
        first-1
        <second1 sa="s1">aaa</second1>
        <second2>bbb</second2>
        <second3>ccc</second3>
    </first>
    top3
    <first fa="f2" fb="2f">
        first-2
        <second1 sa="s2">ddd</second1>
        <second2>eee</second2>
        <second3>fff</second3>
    </first>
    top4
    <first fa="f3" fb="3f">
        first-3
        <second1 sa="s3">ggg</second1>
        <second2>hhh</second2>
        <second3>iii</second3>
    </first>
</root>






SAXParserFactory只能讀取XML,不能修改、新增

※SAXHandler.java

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
    
public class SAXHandler extends DefaultHandler {
    @Override
    public void startDocument() throws SAXException {
        System.out.println("<?xml version='1.0' encoding='UTF-8'?>");
    }
    
    @Override
    public void endDocument() throws SAXException {
        System.out.println("讀取結束");
    }
    
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        System.out.print("<");
        System.out.print(qName);
        if (attributes != null) {
            for (int i = 0; i < attributes.getLength(); i++) {
                System.out.print(" " + attributes.getQName(i) + "='" + attributes.getValue(i) + "'");
            }
        }
        System.out.print(">");
    }
    
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        System.out.print("</");
        System.out.print(qName);
        System.out.print(">");
    }
    
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        System.out.println(new String(ch, start, length));
    }
}

※startDocument方法只是為了方便閱讀,有可能「'」會被認為不是XML,應該改成「"」



※SAXTest.java 

import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
    
public class SAXTest {
    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();
        parser.parse("src/main/java/xml.xml", new SAXHandler());
    }
}




2017年2月10日 星期五

DocumentBuilderFactory

※xml.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>top1
    top2
    <first fa="f1" fb="1f">
        first-1
        <second1 sa="s1">aaa</second1>
        <second2>bbb</second2>
        <second3>ccc</second3>
    </first>
    top3
    <first fa="f2" fb="2f">
        first-2
        <second1 sa="s2">ddd</second1>
        <second2>eee</second2>
        <second3>fff</second3>
    </first>
    top4
    <first fa="f3" fb="3f">
        first-3
        <second1 sa="s3">ggg</second1>
        <second2>hhh</second2>
        <second3>iii</second3>
    </first>
</root>




※讀取元素

import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
    
public class Test {
    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse("src/main/java/xml.xml");
    
        NodeList nl = doc.getElementsByTagName("root");
        for (int i = 0; i < nl.getLength(); i++) {
            Node rootNode = nl.item(i);
            // System.out.println(rootNode.getNodeName());
            // System.out.println(rootNode.getNodeType());
            // System.out.println(rootNode.getNodeValue());
            // System.out.println(rootNode.getTextContent());
    
            Node fChildNode = rootNode.getFirstChild();
            // System.out.println(fChildNode.getNodeName());
            // System.out.println(fChildNode.getNodeType());
            // System.out.println(fChildNode.getNodeValue());
            // System.out.println(fChildNode.getTextContent());
    
            NodeList nodeList = rootNode.getChildNodes();
            for (int j = 0; j < nodeList.getLength(); j++) {
                Node nn = nodeList.item(j);
                System.out.println(nn.getNodeName());
                System.out.println(nn.getNodeType());
                System.out.println(nn.getNodeValue());
                System.out.println("------------------");
            }
        }
    }
}

※如果XML不是讀檔,而是傳來一個String,裡面是XML,可以用
InputStream in = new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
再把in放在builder.parse裡即可

※Node.getNodeType()會回傳一個數字,API 寫的不清楚,要看Node.class的介面原碼才知道,
1是元素、2屬性、3文字,一般就用這三個

※要注意元素和元素之間的空,也算節點



※讀取屬性

import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
    
public class Test {
    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse("src/main/java/xml.xml");
    
        NodeList nl = doc.getElementsByTagName("root");
        for (int i = 0; i < nl.getLength(); i++) {
            Node rootNode = nl.item(i);
            NodeList nodeList = rootNode.getChildNodes();
            for (int j = 0; j < nodeList.getLength(); j++) {
                Node nn = nodeList.item(j);
                if (Node.ELEMENT_NODE == nn.getNodeType()) {
                    System.out.println(nn.getNodeName());
                    NamedNodeMap attrs = nn.getAttributes();
                    for (int k = 0; k < attrs.getLength(); k++) {
                        Node attr = attrs.item(k);
                        System.out.println(attr.getNodeName());
                        System.out.println(attr.getNodeValue());
                        System.out.println("------------------");
                    }
                    System.out.println("===================");
                }
            }
        }
    }
}

※nodeList回傳7,因為元素和元素之間也算節點,所以用Node.ELEMENT_NODE過濾掉
三個first算3個節點,還有first和first之間又有2個節點,最後first和root之間也有兩個節點,所以是7
最後的first和root雖然我沒寫文字,但還是節點

※讀到的text節點是有tab和換行的,不想要可以trim()掉



※寫檔

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
    
public class Test {
    public static void main(String[] args)
            throws ParserConfigurationException, SAXException, IOException, TransformerException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
    
        Document doc = builder.newDocument();
        // 新增元素
        Element root = doc.createElement("root");
        Element first = doc.createElement("first");
        Element second1 = doc.createElement("second1");
        Element second2 = doc.createElement("second2");
        Element second3 = doc.createElement("second3");
    
        // 元素的text
        root.appendChild(doc.createTextNode("top1" + System.getProperty("line.separator") + "\ttop2"));
        first.appendChild(doc.createTextNode("\tfirst-1"));
        second1.appendChild(doc.createTextNode("aaa"));
        second2.appendChild(doc.createTextNode("bbb"));
        second3.appendChild(doc.createTextNode("ccc"));
    
        // 元素組合
        root.appendChild(first);
        first.appendChild(second1);
        first.appendChild(second2);
        first.appendChild(second3);
    
        // 元素屬性
        first.setAttribute("fa", "f1");
        first.setAttribute("fb", "1f");
        second1.setAttribute("sa", "s1");
    
        doc.appendChild(root);
        DOMSource source = new DOMSource(doc);
    
        // 生成output
        File file = new File("D:/" + File.separator + "xml.xml");
        OutputStream out = new FileOutputStream(file, true);
        StreamResult result = new StreamResult(out);
    
        // 生成檔案
        TransformerFactory tFactory = TransformerFactory.newInstance();
        Transformer tf = tFactory.newTransformer();
        tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        tf.transform(source, result);
        out.close();
        System.out.println("XML已生成");
    }
}

※生出來的XML是不會排版的

※此例只是寫其中一個first而已

2017年2月8日 星期三

filter (angularJS 三)

官方API,參考這裡

※lowercase、uppercase、currency、orderBy

<html>
    <script type="text/javascript" src="angular.js"></script>
    
    <body ng-app='xxx'>
        <div ng-controller='ooo'>
            <input ng-model='p3'><br />
            lowercase:
            <p>{{p3 | lowercase}}</p>
            ------------------------------ <br />
            uppercase:
            <p>{{p4 | uppercase}}</p>
            ------------------------------ <br />
            currency:
            <p>{{p1 * 2 | currency}}</p>
            ------------------------------ <br />
            orderBy:
            <p ng-repeat='x in p6 | orderBy:"pp1"'>
                {{x.pp1 + '=' + x.pp2}} <br />
                {{x.pp1 | uppercase}} = {{x.pp2 | currency}} <br />
                {{(x.pp1 | uppercase) + '=' + (x.pp2 | currency)}}
            </p>
            ------------------------------ <br />
            filter:
            <p ng-repeat='x in p6 | filter:"B" | orderBy:"pp1"'>
                {{x.pp1 + '=' + x.pp2}} <br />
                {{x.pp1 | uppercase}} = {{x.pp2 | currency}} <br />
                {{(x.pp1 | uppercase) + '=' + (x.pp2 | currency)}}
            </p>
            ------------------------------ <br />
            自定排序:<br />
            <table border="1">
                <th ng-dblclick="orderByXX('pp1')">Fruit</th>
                <th ng-dblclick="orderByXX('pp2')">Price</th>
                <tr ng-repeat="x in p6 | orderBy:orderBySelf">
                    <td>{{x.pp1}}</td>
                    <td>{{x.pp2}}</td>
                </tr>
            </table>
            ------------------------------ <br />
            自定過濾:<br />
            <ul>
                <li ng-repeat="x in p6">
                    {{x | filterSelf}}
                </li>
            </ul>
        </div>
    </body>
</html>
    
<script>
    var app = angular.module('xxx', []);
    app.controller('ooo', ($scope) => {
        $scope.p1 = 123456789;
        $scope.p2 = 'ddD';
        $scope.p3 = 'Bbb';
        $scope.p4 = 'aAA';
        
        $scope.p5 = () => {
            return $scope.p1 + $scope.p4;
        };
    
        $scope.p6 = [
            {pp1:'strawberry', pp2:'90'},
            {pp1:'apple', pp2:'67'},
            {pp1:'banana', pp2:'23'},
            {pp1:'blueberry', pp2:'90'},
            {pp1:'pineapple', pp2:'50'}
        ];
    
        $scope.orderByXX = function(x) {
            $scope.orderBySelf = x;
        }
    });
    
    app.filter('filterSelf', () => {
        return (x) => {
            return x.pp1.toUpperCase();
        };
    });
</script>

※orderBy可用倒序,只要在最後面加上「:"reverse"」,如:
<p ng-repeat='x in p6 | orderBy:"pp1":"reverse"'>

※filter:'b',裡面的字是不分大小寫的

※自定排序配合事件,以上例是在 th 標籤快按滑鼠左鍵兩下可排序

※結果:

lowercase:
bbb
------------------------------
uppercase:
AAA
------------------------------
currency:
$246,913,578.00
------------------------------
orderBy:
apple=67
APPLE = $67.00
APPLE=$67.00
banana=23
BANANA = $23.00
BANANA=$23.00
blueberry=90
BLUEBERRY = $90.00
BLUEBERRY=$90.00
pineapple=50
PINEAPPLE = $50.00
PINEAPPLE=$50.00
strawberry=90
STRAWBERRY = $90.00
STRAWBERRY=$90.00
------------------------------
filter:
banana=23
BANANA = $23.00
BANANA=$23.00
blueberry=90
BLUEBERRY = $90.00
BLUEBERRY=$90.00
strawberry=90
STRAWBERRY = $90.00
STRAWBERRY=$90.00
------------------------------
自定排序:
FruitPrice
strawberry90
apple67
banana23
blueberry90
pineapple50
------------------------------
自定過濾:
  • STRAWBERRY
  • APPLE
  • BANANA
  • BLUEBERRY
  • PINEAPPLE



※date、number、json

<html>
    <script type="text/javascript" src="angular.js"></script>
    
    <body ng-app='xxx'>
        <div ng-controller='ooo'>
            <input ng-model='p1'><br />
            date:
            <p>{{p1 | date}}</p>
            ------------------------------ <br />
            number:
            <p>{{p2 | number}}</p>
            <p>{{p2 | number:0}}</p>
            <p>{{p2 | number:2}}</p>
            <p>{{p2 | number:-1}}</p>
            ------------------------------ <br />
            json:
            <p>{{ p3 | json }}</p>
            <pre>{{ p3 | json }}</pre>
            <pre>{{ p3 | json:4 }}</pre>
        </div>
    </body>
</html>
    
<script>
    var app = angular.module('xxx', []);
    app.controller('ooo', ($scope) => {
        $scope.p1 = '2000-10-01';
        $scope.p2 = 1234.5678;
        $scope.p3 = [
            {pp1:'strawberry', pp2:'90'},
            {pp1:'apple', pp2:'67'},
            {pp1:'banana', pp2:'23'}
        ];
        $scope.p4 = {'a1':5, 'a2':10, 'a3':500};
    });
</script>

※json:4,這個數字是排版的空格有幾個的意思,但只有 pre 標籤有用

※date格式太多了,請參考上面的官網API連結

※結果:

date:
Oct 1, 2000
------------------------------
number:
1,234.568
1,235
1,234.57
1,230
------------------------------
json:
[ { "pp1": "strawberry", "pp2": "90" }, { "pp1": "apple", "pp2": "67" }, { "pp1": "banana", "pp2": "23" } ]
[
  {
    "pp1": "strawberry",
    "pp2": "90"
  },
  {
    "pp1": "apple",
    "pp2": "67"
  },
  {
    "pp1": "banana",
    "pp2": "23"
  }
]
[
    {
        "pp1": "strawberry",
        "pp2": "90"
    },
    {
        "pp1": "apple",
        "pp2": "67"
    },
    {
        "pp1": "banana",
        "pp2": "23"
    }
]




※limitTo

<html>
    <script type="text/javascript" src="angular.js"></script>
    
    <body ng-app='xxx'>
        <div ng-controller='ooo'>
            <p>{{ numArr | limitTo:4 }}</p>
            <p>{{ str | limitTo:7}}</p>
            <p>{{ num | limitTo:3}}</p>
            ------------------------------
            <p>{{ numArr | limitTo:-1 }}</p>
            <p>{{ str | limitTo:-1}}</p>
            <p>{{ num | limitTo:-1}}</p>
        </div>
    </body>
</html>
    
<script>
    var app = angular.module('xxx', []);
    app.controller('ooo', ($scope) => {
        $scope.numArr = [1,2,3,4,5,6,7,8,9];
        $scope.str = "abcdefghi";
        $scope.num = 9876543210;
    });
</script>

※不管是陣列、字串、數字都有效;負的從後面開始取

※結果:
[1,2,3,4]
abcdefg
987
------------------------------
[9]
i
0