Ubuntu上安裝ImageMagick

ImageMagick是一個用於查看、編輯點陣圖文件以及進行圖像格式轉換的開放原始碼軟體套裝。它可以讀取、編輯超過100種圖象格式。 

最基本的一個功能是準確高效地轉換超過68種圖片的格式,包括眾所周知的TIFF、JPEG、PNG、PDF、PhotoCD,以及GIF。ImageMagick支持的格式列表 

在ubuntu的安裝步驟如下:
1.下載你需要的版本,以本文撰寫時版本ImageMagick-6.8.1-8.tar.gz為例。(下載頁面)

2.依序執行以下指令 解壓縮檔案

tar xvfz ImageMagick-6.8.1-8.tar.gz

編譯並安裝

cd ImageMagick-6.8.1-8/
./configure
make
sudo make install
sudo ldconfig /usr/local/lib

測試

/usr/local/bin/convert --version

在Android的TextView上面加上html的連結語法

如果只是想要在Android的view上面連結,不需要使用到WebView,只要使用TexView就可以完成。

網路上很多資料都說要在layout.xml的TextView裡加上

android:linksClickable="true"

或是

android:autoLink="web"

其實實際側試過後,這兩行都不需要設定,只要加上MovementMethod就可以,而內容文字則是透過Html.fromHtml(html)來做轉換,參考範例如下:

TextView tvLinks = (TextView)findViewById(R.id.my_links);
tvLinks.setMovementMethod(LinkMovementMethod.getInstance());
tvLinks.setText(Html.fromHtml("<a href='http://blog.examtw.net'>璟程資訊部落格</a>"));

在Grails執行例行性工作(Schedule Service)

如果你的專案有類似以下的需求
1.每天凌晨2點需要統計系統的資料,例如股價、財務
2.每週日寄發電子報給用戶
3.每15分鐘檢查系統資料,或是抓取外部系統資訊

類似這些需要定期執行的工作,你可以使用Schedule Service的方式,在Grails裡面它有整合Java原本就非常好用的Quartz,安裝方式也非常的無腦。

在指令列下輸入
grails install-plugin quartz

等它安裝完成後,你的系統就可以使用Quartz了


接下來你要做的就是新增一個工作(Job)
在指令列下輸入
grails create-job [job class名稱]

系統會在grails-appjobs 下建立新的Job Class

class CouponJob {
    static triggers = {
      cron name: ‘couponStatusTrigger’, cronExpression: “0 32 11 * * ?"
    }

    def execute() {
        println(“hello……….")
    }
}

比較重要的是你的cronExpression,總共有七個參數“s m h D M W Y"
其中前六個為必須的,分別是
Second, 0-59
Minute, 0-59
Hour, 0-23
Day of Month, 1-31, ?     (實際測試,如果不指定需要輸入*)
Month, 1-12 or JAN-DEC  (實際測試,如果不指定需要輸入*)
Day of Week, 1-7 or SUN-SAT, ?  (實際測試,如果不指定需要輸入?)

第七個參數是年,非必要欄位
Year [optional]

如同上述程式碼,就會在每天的11:32分,執行在execute()的程式碼


當你要使用每一段固定時間,執行相同的工作時,可以使用simple的設定

class CouponJob {
    static triggers = {
      simple name: ‘couponStatusTrigger’, startDelay:3000, repeatInterval: 1000, repeatCount: 2
 
    }
def i=1
def execute() {
//println(“hello……….#"+i)
log.info(“hello……….#"+i)
i=i+1
    }
}

主要就是設定以下參數
startDelay:單位是毫秒,是當系統啟動多久後開始執行第一次任務
repeatInterval:單位是毫秒,是每隔多久執行一次(舊版好像是叫做timeout)
repeatCount:重複次數,如果是2代表是執行3次(重複2次的意思),所以0代表執行一次,-1則表示一直執行

另外注意兩點
1.每一次執行Job,等於重新init class,所以上述例子,每次印出來的i均為1,不會累加
2.我mark起來是println輸出到console去驗證結果,結果很神奇的只會執行第一次,一直以為Quartz不能跑,後來改成log.info就可以正常運作了

其他更詳細的設定可以參考官方網站:
Grails Quartz Plugin
Grails Quartz Plugin Doc

Grails+Spring Security Core Plugin(Part3)

上次在Part1中,我們設定好了Spring Security,也提到了Spring Security可以有三種方式,Annotation、Static URL、Dynamic Request Maps,而在Part2裡面我們則是新增好對應的User、Role並且可以正常登入。接下較要把Security真正套用在Project上面,我一開始使用的是這篇文章裡面提到的Static URL的方式,作法如下:

修改設定檔Config.groovy
加上以下程式

1.設定securityConfigType =InterceptUrlMap
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap

2.設定你的頁面權限,這部份要注意順序,因為Spring Security Core會從第一個開始比對,所以如果你把’/**’放在最前面,後面的就完成失效,所以涵蓋範圍越大的要放在越後面

這裡我們設定/login/*是不需要登入,也就是使用IS_AUTHENTICATED_ANONYMOUSLY這個屬性
而其他頁面則需要登入(可以使用RemeberMe)。

grails.plugins.springsecurity.interceptUrlMap = [
   ‘/login/*’:         [‘IS_AUTHENTICATED_ANONYMOUSLY’],
   ‘/**’:               [‘IS_AUTHENTICATED_REMEMBERED’]
]

這樣一來,代表系統除了Login外所有的頁面,都必須要登入過後才可以存取

如果你還要寫一個使用者可以註冊的介面,你是寫在userController的rigister與register_save,就再login後面加上

 ‘/user/register*’:         [‘IS_AUTHENTICATED_ANONYMOUSLY’],

如果其他user的新增、刪除、修改功能要限制管理者才可以做的話,就加上

‘/user/*’:         [‘ROLE_ADMIN’],

這段就務必要放在 ‘/user/register*’:  設定的面,否則使用者永遠到不了註冊頁面

最後,我們在整個網站上的右上角加上登入/登出以及註冊的連結,整個登入的機制就很完整了

開啟views/layouts/main.gsp
找到<div align=right id="globalAction">這行
加上以下程式碼

<sec:ifNotLoggedIn>
<g:link controller="login" action="auth"><g:message code="default.login.label"/></g:link>&nbsp;&nbsp;&nbsp;
<g:link controller="user" action="register"><g:message code="default.register.label"/></g:link>
</sec:ifNotLoggedIn>
<sec:ifLoggedIn>
<sec:username /> (<g:link controller="logout"><g:message code="default.logout.label"/></g:link>)
</sec:ifLoggedIn>
(default.login.label、default.register.label、default.logout.label要自己加入多國語系檔唷)

這樣如果你尚未登入,就會顯示登入與註冊連結;當你已經登 入 ,則會顯示你的登入名稱與登出連結,如圖

在Discuz文章內加上社群分享按鈕

要在Discuz的文章上面加上如Facebook like(讚)、Google+ +1按鈕時,必須要去修改它的template file。

在此之前先決定你要放上哪些按鈕

Facebook like的官方產生器
Google+ +1按鈕的官方產生器
AddThis一次產生Facebook、Twitter與Pinterest分享,還有其他書籤服務按鈕

透過以上服務產生你的程式碼,之後只要找到對應的位置貼上就可以了

我這裡的作法是貼在文章的第一行,步驟如下:

  1. 開啟templatedefaultforumviewthread_node.htm
  2. 找到<div class="pct">這行
  3. 在<div class="pct">後面貼上你獲得的程式碼

效果可以參考這裡 http://urstock.net/forum/forum.php?mod=viewthread&tid=2526&extra=page%3D1

Grails+Mail Plugin設定與使用教學

使用Grails的好處就是有很多包裝好的Plugin可以使用,這次要用的是Mail Plugin ,安裝方式一樣很簡單。

打入以下指令 grails install-plugin mail (如果是在STS中使用,則不用打grails)


嗯,裝完了XD,很沒成就感吧^^


接下來在Config.groovy設定就可,直接在最後面加上以下設定

官網舉了三個常用的email smtp設定,包括了Gmail、Hotmail與Yahoo Mail,如果你是要用這三種設定,直接套用就可以了,當然要記得改你自己要用的帳號密碼。

Gmail
grails {

   mail {
host =
"smtp.gmail.com"
port = 465
username =
"youracount@gmail.com"
password =
"yourpassword"
props = [
"mail.smtp.auth":"true",
"mail.smtp.socketFactory.port":"465",
"mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback":"false"]

}
}




Hotmail

grails {
mail {
host = "smtp.live.com"
port = 587
username = "youracount@live.com"
password = "yourpassword"
props = ["mail.smtp.starttls.enable":"true",
"mail.smtp.port":"587"]

}
}

Yahoo mail
grails {
mail {
host = "smtp.correo.yahoo.es"
port = 465
username = "myuser"
password = "mypassword"
props = [ "mail.smtp.auth":"true",
"mail.smtp.socketFactory.port":"465",
"mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback":"false" ]
}
}
接下來就可以直接在程式中使用mail的功能
最簡單的文字email
sendMail {     
to "fred@g2one.com"
subject "Hello Fred"
body 'How are you?'
}
當然可以加上副本、密件副本、多個收件者
mailService.sendMail {
to "fred@g2one.com","ginger@g2one.com"
from "john@g2one.com"
cc "marge@g2one.com", "ed@g2one.com"
bcc "joe@g2one.com"
subject "Hello John"
body 'this is some text'
}
也可以寄送HTML郵件
sendMail {
to "fred@g2one.com"
subject "Hello John"
html '<b>Hello</b> World'
}
甚至可以套模版
sendMail {
to "john@g2one.com"
subject "Hello John"
html g.render(template:"myMailTemplate")
}
最重要的附加檔案,也變得好方便
sendMail {
multipart true
to issue.watchers.email.toArray()
subject "The issue you watch has been updated"
body "Hello Watcher!"
attachBytes "Some-File-Name.xml", "text/xml", contentOrder.getBytes("UTF-8")
//To get started quickly, try the following
//attachBytes './web-app/images/grails_logo.jpg','image/jpg', new File('./web-app/images/grails_logo.jpg').readBytes()
}

Grails的資料庫設定(MySQL)

Grails的預設資料庫是H2 database,如果要改成MySQL,只要幾個步驟就可以搞定。

1.下載JDBC driver for MySQL.
2.將jar放到Grails專案的lib資料夾內
3.安裝MySQL並設定好帳號、密碼以及資料庫
4.修改Grails專案內confDataSource.groovy



dataSource {
    pooled = true
    driverClassName = “com.mysql.jdbc.Driver"
    //dialect = “org.hibernate.dialect.MySQL5InnoDBDialect"

username = “帳號
password = “密碼
}
hibernate {
    cache.use_second_level_cache = true
    cache.use_query_cache = true
    cache.provider_class = ‘net.sf.ehcache.hibernate.EhCacheProvider’
}
// environment specific settings
environments {
    development {
        dataSource {
            dbCreate = “create" // one of ‘create’, ‘create-drop’,’update’
            url = “jdbc:mysql://localhost:3306/資料庫名稱?useUnicode=yes&characterEncoding=UTF-8″

    username = “帳號
    password = “密碼

        }
        hibernate {
            show_sql = true
        }
    }
    test {
        dataSource {
            dbCreate = “create-drop" // one of ‘create’, ‘create-drop’,’update’
            url = “jdbc:mysql://localhost:3306/ 資料庫名稱 ?useUnicode=yes&characterEncoding=UTF-8″

    username = “帳號
    password = “密碼

        }
    }
    production {
        dataSource {
            dbCreate = “update"
            url = “jdbc:mysql://localhost:3306/ 資料庫名稱 ?useUnicode=yes&characterEncoding=UTF-8″

    username = “帳號
    password = “密碼

        }
    }
}

  • 上述紅色部分需要修改成自己的設定
  • 資料庫可以在development/test/production中設定不同的資料庫以及帳號密碼
  • dbCreate則是設定你對資料庫所做的動作,分別有create,create-drop,update
5.如果你之前有用h2跑過專案,這裡強烈建議要先跑過grails clean指令,才可以讓新的資料庫設定正常運作。

Grails+Spring Security Core Plugin(Part2)

上次在Part1的設定中,已經可以成功安裝Spring Security在Grails專案內,接下來可以新增預設的admin使用者來測試看看是否有效。

我們可以在confBootStrap.groovy裡面建立系統啟動時預設跑的程式碼
(雖然使用Grails的Eclipse開發環境可以動態的更新Server程式碼,但是這部份還是必須關掉Server重新啟動材可以生效)
在Bootstrap的init()裡面加下以下程式碼
def userRole = SysRole.findByAuthority('ROLE_USER') ?: new SysRole(authority: 'ROLE_USER').save(failOnError: true)
def adminRole = SysRole.findByAuthority('ROLE_ADMIN') ?: new SysRole(authority: 'ROLE_ADMIN').save(failOnError: true)

以上是檢查ROLE_USER以及ROLE_ADMIN這兩個角色是否存在,不存在則自動加上去
需注意,程式碼內的SysRole與SysUser需根據Part1的設定而有不同。

接下來新增admin這個使用者,並且設定為ROLE_ADMIN
def adminUser = SysUser.findByUsername('admin') ?: new SysUser(
username: 'admin',
password: springSecurityService.encodePassword('admin'),
enabled: true).save(failOnError: true)

if (!adminUser.authorities.contains(adminRole)) {
SysUserSysRole.create adminUser, adminRole
}

如果是使用Spring Security1.2版以後的版本,會發生無法登入的狀況

Sorry, we were not able to find a user with that username and password.


主要是因為password在1.2版時function內部就會自動編碼,
因此不用額外加上springSecurityService.encodePassword('admin')
將這部分直接修改為'admin'後,就可以順利用admin/admin登入了。


推薦好用的JSON工具

JSON(Javascript Object Notation)是一種輕量級的資料交換語言,以文字為基礎,且易於讓人閱讀。儘管JSON是在Javascript的一個子集,但JSON是獨立於語言的文本格式,並且採用了類似於C語言家族的一些習慣。(維基百科)

JSON現在愈來越普及了,因為它有XML結構化的特性,卻又省去了不必要的贅字,讓解析、傳輸的效能都比較好,尤其是在AJAX的應用上更是廣泛,這裡介紹兩個好用的線上工具:JSON Editor與JSON 2 HTML

1.JSON Editor
透過樹狀結構編輯,可以用來設計你的JSON內容,你可以從根節點一步步建立object/array/string/number…等節點,甚至還可以整個節點複製/剪下/貼上,是我目前看到最方便的線上工具。

當然你也可以把你現有的JSON String貼到上面去驗證、解析甚至修改。

2.JSON 2 HTML
設計完JSON後,現有的JSON String可讀性比較差,這個網站提供你轉成HTML格式,而且還不是單純的靜態HTML唷,你可以隨時針對各節點進行展開/收合。讓你更能夠一目了然的閱讀JSON String,很適合團隊或與客戶進行討論溝通。

Grails+Spring Security Core Plugin(Part1)

最近開始練習用Grails開發專案,除了MVC的功能外,最需要的就是Security的部份,也就是使用者登入、角色權限等功能不用自己去寫,而是套用現有開發很完整的Security Framework。好處除了不用自己開發使用者登入、密碼編碼、角色權限設計等繁瑣工作外,完整的framework通常還可以根據網址、頁面設定不同的權限,穩定度也比自己開發好。

以往用Appfuse開發時,內建是使用Acegi,在Grails裡也有支援Acegi的Plugin,但是評價最高的是Spring Security Core Plugin,因此這次就先改用Spring Security Core Plugin看看。

1.安裝Spring Security Core Plugin
在Grails裡面安裝套件非常簡單,指需要在打入以下指令即可

grails install-plugin spring-security-core

安裝完以後,就要開始設定對應的User/Role

2.設定User/Role類別
接下來要為SpringSecurity建立相對應的User(使用者)、Role(角色)以及UserRole(使用者角色對應)的類別,這部份沒有自動產生是考量到與現有系統使用者的整合,假設你原本系統就有設計User/Role/UserRole類別,則Spring Security需要改用其他名稱。

但是如果兩個User希望整合在一起,官網上建議是以Spring Security的User為父類別,透過繼承的方式來建立自己需要的User類別,這樣在未來Spring Security有變動時,才不會影響到現有程式碼。

建立的指令如下

grails s2-quickstart org.example SysUser SysRole

org.example是你希望的package
SysUser,SysRole則是你定義的User/Role類別名稱,系統會自動在產生SysUserSysRole的類別

程式會自動產生以下檔案

domain classes:
org.example.SecUser
org.example.SecRole
org.example.SecUserSecRole


controllers:
LoginController
LogoutController


views:
login*.*

到UrlMappings.groovy裡面設定login/logout url該導向哪個action,加上下面這段:

“/login/$action?"(controller: “login")
“/logout/$action?"(controller: “logout")

預設的登入畫面

接下來就可以針對頁面設定權限了





3.設定頁面權限
描述角色的方式有兩種
a.資料庫內的Role
b.系統預設的Role
其中資料庫內的Role視專案需求而定,系統預設的包過以下三種
[IS_AUTHENTICATED_ANONYMOUSLY]
任何人都可以存取,不需要登入系統

[IS_AUTHENTICATED_REMEMBERED]
必須為登入的使用者,曾經登入過,且選擇remember me的使用者亦可。通常用來限制使用較不危害系統資料的功能(如檢視)。

[IS_AUTHENTICATED_FULLY]
使用者必須確認是登入過的,即使使用remember me的使用者,也必須重新登入。通常用來限制較嚴謹得功能(如發佈資訊)。

設定頁面權限的方式有三種
a.Annotations
Annotation提供我們可以在controller內自定每一個action的權限,只要在該action上面加上@Secured的annotation tag就可以,語法如下:

@Secured([‘ROLE_USER’])
def index() {…. }

@Secured([‘ROLE_USER’, ‘IS_AUTHENTICATED_FULLY’])

def index() {…. }

b.Static URL rules
修改設定檔Config.groovy,可以定義全局網址的權限設定

grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap
grails.plugins.springsecurity.interceptUrlMap = [
    ‘/timeline’:         [‘ROLE_USER’],
    ‘/person/*’:         [‘IS_AUTHENTICATED_REMEMBERED’],
    ‘/post/followAjax’:  [‘ROLE_USER’],
    ‘/post/addPostAjax’: [‘ROLE_USER’, ‘IS_AUTHENTICATED_FULLY’],
    ‘/**’:               [‘IS_AUTHENTICATED_ANONYMOUSLY’]
]

比對權限方式是有照順序的,因此如果第一個邏輯成立,則不再比對其他。例如上述例子的最後一項指的是不需要登入即可存取網站,如果擺在第一項,則其他權限就沒有作用了,需要謹慎使用。

c.Dynamic request maps
此方法是當你有動態頁面權限需求時,可以把設定的內容寫入資料庫內,這時候你或得到的是彈性,但是也失去了些許的系統效能。使用方法如下:

修改設定檔Config.groovy
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.Requestmap

建立一個Requestmap的class

在Bootstrap.groovy建立載入的資料

new Requestmap(url: ‘/timeline’, configAttribute: ‘ROLE_USER’).save()
new Requestmap(url: ‘/person/*’, configAttribute: ‘IS_AUTHENTICATED_REMEMBERED’).save()
new Requestmap(url: ‘/post/followAjax’, configAttribute: ‘ROLE_USER’).save()
new Requestmap(url: ‘/post/addPostAjax’, configAttribute: ‘ROLE_USER,IS_AUTHENTICATED_FULLY’).save()
new Requestmap(url: ‘/**’, configAttribute: ‘IS_AUTHENTICATED_ANONYMOUSLY’).save()

更進階的使用,可以參考