<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理

    讀R4R,才讀完第2章,前兩章沒什么新內容,算是復習吧

    rails的lifecycle:
    test3.jpg

    從瀏覽器發起一個請求的基本流程:

    A.server to dispatcher

    服務器通過你指定的路徑查找dispatcher,比如,你在apache配置:

    <VirtualHost www.r4rmusic.com>
    ServerName www.r4rmusic.com
    ServerAlias r4rmusic.com
    DocumentRoot "/usr/local/share/railsapps/r4rmusic/public/"
    </VirtualHost>

    服務器將在"/usr/local/share/railsapps/r4rmusic/public/下查找分發器,在rails應用下面有這么幾個文件就是:dispatch.cgi dispatch.fcgi dispatch.rb

    這幾個文件中的某個將被調用

    B.dispatcher to controller

    分發器將解析發起請求的URL,按照:

    1.controller的名稱

    2.action名稱

    3.請求id值

    來尋找相應的controller的action,并執行.當然,你可以通過編輯config下面的routes.rb來定義自己的路由規則

    C.performance of a controller action

    當相應的controller以及相應的action被找到并且執行,他們將可以訪問:

    1.CGI數據,form提交的數據

    2.controller的session信息,內建的session方法

    本質上rails是把業務邏輯放在controller的action里面,也就是沒有我們在J2EE中所謂的業務邏輯層.當業務邏輯或者說action較多時,你的controller文件不可避免的變的很長...在維護性和可讀性也許會帶來問題,當然,細分controller是更好的方法

    posted @ 2007-02-06 13:37 dennis 閱讀(448) | 評論 (0)編輯 收藏

    來自railscn的討論:

    http://www.railscn.com/viewtopic.php?t=2289

    ?

    1 . eval ? " obj?=?#{str}.new " ??? # 只能在irb中使用
    2 . obj? = ? eval ? " obj?=?#{str}.new " ?
    3 . obj? = ? eval (str) . new
    4 . c? = ?Object . const_get( " Array " )?
    ??s?
    = ?c . new

    ?

    相比于java的class.forName,與javascript等腳本語言一致,更為簡單和輕量級?

    posted @ 2007-02-06 13:35 dennis 閱讀(264) | 評論 (0)編輯 收藏

    剛學ruby時寫的工具,我自己一直在用,放在桌面上,遇到不懂單詞就得問它。發在railscn上,ranchgirl修改的更為ruby way。

    ?受blogjava上的帖子啟發,實在是個有趣的主意,寫了個ruby版本的,對俺這等英語一般的同學來說,google在線翻譯經常使用吶,原貼之java版
    http://www.tkk7.com/ekinglong/archive/2006/11/12/80704.html?Pending=true#Post

    require?'net/http'
    def?translate
    ??txt
    =STDIN.gets
    ??break?
    if?txt.strip=='e'?or?txt.strip=='exit'
    ??temp
    =txt.split('?')
    ??
    if?temp[1]=='1'?or?temp.size==1
    ????langpair
    ='en|zh-CN'
    ??
    else
    ????langpair
    ='zh-CN|en'
    ??end
    ?
    #使用代理??
    ??$proxy_addr?=?'127.0.0.1'
    ??
    $proxy_port?=?80

    ??response?
    =?Net::HTTP.Proxy($proxy_addr,?$proxy_port).post_form(URI.parse("http://translate.google.com/translate_t"),{'text'=>temp[0],'langpair'=>langpair})

    ??response
    .body?=~?/<div?id=result_box?dir=ltr>(.*)<\/div>/
    ??result?
    =?$1?
    ??puts?'翻譯內容:'+temp[0]
    ??puts?
    'google返回:'+result
    ??puts?
    '-------------------退出請打e或者exit---------------'
    ??translate
    end
    translate


    ranchgirl修改的版本,沒有使用遞歸:
    require?'net/http'
    def?usage
    ??
    "usage:?word?[lang2?[lang1]]\n"?+
    ??
    "Translate?word?from?lang1?(default?en,?English)?to?lang2?(default?es,?Spanish)\n"?+
    ??
    "ISO?language?code:?http://www.unicode.org/unicode/onlinedat/languages.html"?
    end
    def?translate
    ??arr?
    =?ARGV
    ??
    if?!arr[0]?then?puts?usage;?return?end
    ??arr[
    1]?=?"es"?unless?arr[1]
    ??arr[
    2]?=?"en"?unless?arr[2]?
    ??langpair?
    =?"#{arr[2]}|#{arr[1]}"???
    ??response?
    =?Net::HTTP.post_form(URI.parse("http://translate.google.com/translate_t"),
    ?????????????????????????????????{
    :text?=>?arr[0],?:langpair?=>?langpair})
    ??response
    .body?=~?/<div?id=result_box?dir=ltr>(.*)<\/div>/
    ??result?
    =?$1?
    ??result?
    =?"No?#{langpair}?translation?available?for?#{arr[0]}"?if?result.size?==?0
    ??puts?result
    end
    translate?

    posted @ 2007-02-06 13:33 dennis 閱讀(1640) | 評論 (3)編輯 收藏

    ?項目算完成了,等測試報告出來的時間里玩玩groovy,不玩不知道,一玩嚇一跳,groovy與ruby好象啊。
    看看下面的代碼:
    ruby:
    [
    1,2,3,4,5,6,7].inject(0){|sum,i|?sum+=i}

    groovy:

    [
    1,2,3,4,5,6,7].inject(0){sum,i?->?sum+=i}


    ruby的closures與groovy的closures機制幾乎完全一樣,除了符號改變之外。有興趣的話看看這個:
    http://groovy.codehaus.org/Tutorial+2+-+Code+as+data%2C+or+closures

    如果說groovy有什么優點的話,就是它可以直接利用java豐富的類庫,實在爽:
    //readFile.groovy
    myFileName?
    =?"E://groovy//readFile.groovy"
    myFile?
    =?new?File(?myFileName)
    printFileLine?
    =?{?println?"File?line:?"?+?it?}
    myFile
    .eachLine(?printFileLine?)


    語法層面沒什么好談的,我更希望了解下groovy在實際應用中的表現,IBM的develper works上面有個實戰groovy系列,值的好好讀讀

    補充下,在spring中調用groovy beans的方法:
    首先需要一個java接口,比如:

    package?com.sohu.blog.dennis_zane.springdemo.scripting;

    public?interface?Calculator?{
    ???
    int?add(int?x,int?y);
    }

    然后是Groovy?bean
    :
    //GroovyCalculator.groovy
    package?com.sohu.blog.dennis_zane.springdemo.scripting;
    class?GroovyCalculator?implements?Calculator{
    ??
    int?add(int?x,?int?y){
    ??????x
    +y????
    ??}
    }

    在spring配置文件中配置:

    <lang:groovy?id="calculator"?script-source="classpath:/com/sohu/blog/dennis_zane/springdemo/scripting/GroovyCalculator.groovy"/>


    調用的話跟使用一般的bean沒什么不同:

    Calculator?calculator=(Calculator)ctx.getBean("calculator");
    System.out.println(calculator.add(100,?20));

    也許隨著groovy性能的提升,將業務層完全由動態語言來實現不是沒有可能。

    ?

    posted @ 2007-02-06 13:11 dennis 閱讀(484) | 評論 (0)編輯 收藏

    ruby語言本身并沒有提供abstract class和abstract method機制。這是ruby的spirit所決定的。但如果我們真的需要定義一個公共抽象類(或者抽象方法)來讓子類來實現,又該如何做呢?
    ??? 我們可以通過在調用方法時拋出NotImplementedError來防止方法被調用。如(來自《ruby cookbook》的例子):

    ?class?Shape2D
    ??def?area
    ????raise?NotImplementedError
    .new("#{self.class.name}#area是抽象方法")
    ??end
    end?
    class?Square?
    <?Shape2D
    ??def?initialize(
    length)
    ????
    @length?=?length
    ??end
    ??
    ??def?area
    ????
    @length?**?2
    ??end
    end


    ?? 父類
    Shape2D的方法area就是我們所需要的“抽象方法”了。你不能直接調用:

    s1=Shape2D.new
    s1
    .area

    這樣調用將拋出錯誤:Shape2D#area是抽象方法 (NotImplementedError)
    Shape2D的子類Square覆寫了此方法。由此我們模擬實現了抽象方法。那么抽象類該如何實現呢?自然而然,我們想到如果把類的initialize方法這樣處理,那么這樣的類將沒辦法被new生成,不正是我們所需要的抽象類?說干就干:

    ?class?Shape2D
    ??def?initialize
    ????raise?NotImplementedError
    .new("#{self.class.name}#area是抽象類")
    ??end
    ??def?area
    ????raise?NotImplementedError
    .new("#{self.class.name}#area是抽象方法")
    ??end
    end?


    當你調用Shape2D.new時,解釋器將提示你:Shape2D是抽象類(NotImplementedError)

    我們已經實現了抽象方法和抽象類,感覺還是不夠好,對每一個需要實現抽象類的類來說,我們都需要去寫一句:raise NotImplementedError.new...實在不夠爽。ruby鼓勵我們去修改類的行為,甚至是標準庫,那好,我們修改Class類吧,提供類似attr_reader的聲明式服務:
    class?Class
    ??def??
    ????abstract(
    *args)
    ????args
    .each?do?|method_name|
    ??????
    ??????define_method(method_name)?
    do?|*args|
    ????????
    if?method_name?==?:initialize???
    ??????????msg?
    =?"#{self.class.name}是抽象類"
    ????????
    else
    ??????????msg?
    =?"#{self.class.name}##{method_name}是抽象方法"
    ????????end
    ????????raise?NotImplementedError
    .new(msg)
    ????????
    ??????end
    ????end
    ??end
    end


    OK,如此一來,我們的Shape2D可以寫成:
    ?class?Shape2D
    ????abstract
    :initialize,:area??#initialize和area是抽象方法
    ?end


    盡管在ruby中,抽象類和抽象方法是否有用存在懷疑,不過知道這樣的辦法總是不錯的主意

    posted @ 2007-02-06 13:07 dennis 閱讀(1452) | 評論 (1)編輯 收藏

    rails1.1已經加入對json的全面支持,現在的Array,Hash,String,Object...等等都有一個to_json方法,生成 json字符串。反過來,我們該如何解析json呢?查了下http://www.json.org/上面ruby語言的鏈接,在rubyforge上找到了一個項目。解析json對ruby來說非常簡單,只要一行代碼:



    例子:
    json?=?'["a",?"B",?"C"]'
    ?
    puts?"Unsafe?#{unsafe_json(json).inspect}"???#輸出Unsafe?["a",?"B",?"C"]






    把上面的json字符串解析成Array。這樣的方法并不安全,比如:
    json?=?'puts?"Danger?Will?Robinson"'
    ? puts?"Unsafe?#{unsafe_json(json).inspect}"?







    又該輸出什么呢?很遺憾,解析不出什么東西,跳出一個警告:
    warning: character class has `[' without escape


    安全的方法如下:
    module?SafeJSON
    ??require?
    'monitor'
    ??def?SafeJSON.build_safe_json
    ????ret?
    =?nil
    ????waiter?
    =?''
    ????waiter.extend(MonitorMixin)
    ????wait_cond?
    =?waiter.new_cond
    ????
    ????Thread.start?
    do
    ??????$SAFE?
    =?4
    ??????ret?
    =?Proc.new?{|json|
    ????????eval(json.gsub(
    /(["'])/s*:/s*(['"0-9tfn/[{])/){"#{$1}=>#{$2}"})
    ??????}

    ??????waiter.synchronize?
    do
    ????????wait_cond.signal
    ??????end
    ????end
    ????waiter.synchronize?
    do
    ??????wait_cond.wait_while?
    {?ret.nil??}
    ????end
    ????
    return?ret
    ??end
    ??@@parser?
    =?SafeJSON.build_safe_json
    ??
    ??#?Safely?parse?the?JSON?input
    ??def?SafeJSON.parse(input)
    ????@@parser.call(input)
    ??rescue?SecurityError
    ????
    return?nil
    ??end
    end






    包含這個Module,你就可以這樣使用:
    peoples=SafeJSON.parse('{"peoples":[{"name":"site120","email":"site120@163.com","sex":"男"},{"name":"site120_2","email":"site120@163.com_2","sex":"男_2"}]}')

    puts?peoples[
    "peoples"][1]["name"]??#輸出site120_2







    rails通過RJS內置了對AJAX的支持,也許用到json的機會并不多,不過作為一種數據交換的方便格式,還是值的注意。

    posted @ 2007-02-06 13:04 dennis 閱讀(4680) | 評論 (1)編輯 收藏

    ?雖然sohu不大可能倒閉,但是我也想導出我所有的文章,備份在自己的數據庫中。javaeye的blog系統提供了一個blog導入導出的功能,用起來很酷。其實你自己用ruby寫一下也很簡單,比如我要讀取我的blog的RSS源:

    require?
    'rss/2.0'
    require?
    'open-uri'
    url?
    =?'http://dennnis-zane.blog.sohu.com/rss'
    feed?
    =?RSS::Parser.parse(open(url).read,?false)?
    puts?
    "===?blog名稱:?#{feed.channel.title}?==="?
    feed.items.each?
    do?|item|?
    ????puts?item.title?
    ????puts?
    "?(#{item.link})"
    ????puts?puts?item.description?
    end?

    feed.items對應rss2.0的item元素,每個item元素描述了一篇文章的標題,鏈接,內容等信息,你可以通過item.title,item.link等來讀取,并存入你自己的數據庫。

    再給一個使用代理的例子,因為我的機子是使用代理上網的:

    require?'rss/2.0'
    require?
    'net/http'
    url?
    =?'http://dennnis-zane.blog.sohu.com/rss'
    $proxy_addr?
    =?'172.16.51.10'
    $proxy_port?
    =?807

    response?
    =?Net::HTTP.Proxy($proxy_addr,?$proxy_port).get_response(URI.parse("http://dennnis-zane.blog.sohu.com/rss"))
    feed?
    =?RSS::Parser.parse(response.body,?false)
    puts?
    "===?Channel:?#{Iconv.conv('GBK','UTF-8',feed.channel.title)}?==="
    feed.items.each?
    do?|item|
    ??puts?Iconv.conv(
    'GBK','UTF-8',item.title)
    ??puts?
    "?(#{item.link})"
    ??puts
    ?#?puts?Iconv.conv(
    'GBK','UTF-8',item.description)
    end


    打印:

    === Channel: 花非花 ===
    websphere錯誤備忘錄
    ?(http://dennnis-zane.blog.sohu.com/29898836.html)

    感冒,寒冷的夜
    ?(http://dennnis-zane.blog.sohu.com/29859082.html)

    ECMAScript對象基礎
    ?(http://dennnis-zane.blog.sohu.com/29499101.html)

    用ruby創建領域特定語言(DSL)——轉載
    ?(http://dennnis-zane.blog.sohu.com/29350052.html)

    使用ruby解析json
    ?(http://dennnis-zane.blog.sohu.com/29200192.html)

    ruby實現抽象類和抽象方法
    ?(http://dennnis-zane.blog.sohu.com/29145303.html)

    看了《父子》,看了《綠帽子》
    ?(http://dennnis-zane.blog.sohu.com/29047444.html)

    ECMAScript基礎
    ?(http://dennnis-zane.blog.sohu.com/28876856.html)

    假期結束,專心工作
    ?(http://dennnis-zane.blog.sohu.com/28604494.html)

    不解
    ?(http://dennnis-zane.blog.sohu.com/27564529.html)

    posted @ 2007-02-06 12:57 dennis 閱讀(320) | 評論 (0)編輯 收藏

    呵呵,在《develope J2EE without EJB》中,DTO被狠很地批判了一把,rod說這完全是反模式??蓪嶋H項目當中,我們還是不得不在使用。VO,PO,一牽扯到概念總是多么復雜。。。把一個PO從頭傳到尾??從頁面到數據庫,一捅到底?NO,NO,萬一你要顯示給用戶的是幾個PO的結合怎么辦?萬一我們只是需要某幾個屬性組合在一起顯示怎么辦?一捅到底的策略是多么丑陋,而且你完全把你的數據庫設計模型暴露給用戶。所以我們需要一些map工具來轉換,在這方面,過去我只知道有個 BeanUtils,不夠靈活,而今天,接觸了下dozer,啊,跟spring一樣的理念!靈活多變,你想怎么映射,想怎么換都可以??纯此С值霓D換類型:

    ? Primitive to Primitive Wrapper
    ? Primitive to Custom Wrapper
    ? Primitive Wrapper to Primitive Wrapper

    ? Primitive to Primitive
    ? Complex Type to Complex Type
    ? String to Primitive
    ? String to Primitive Wrapper
    ? String to Complex Type if the Complex Type contains a String constructor
    ? Each of these can be mapped to one another: java.util.Date, java.sql.Date, java.sql.Time,
    java.sql.Timestamp, java.util.Calendar, java.util.GregorianCalendar
    ? String to any of the supported Date/Calendar Objects if an explicit date format mapping attribute is
    specified.
    ? Objects containing a toString() method that produces a long representing time in (ms) to any
    supported Date/Calendar object.

    幾乎我們能想到的,它都提供了方法來做到。而且dozer可以很容易地跟spring集成。下面舉個簡單例子:

    定義一個Book對象:

    package com.denny_blue.dozerdemo;
    public class Book {
    ?private String name;
    ?private String author;
    ?
    ?
    ?public Book(){
    ??
    ?}?
    ?public void setAuthor(String author) {
    ??this.author = author;
    ?}

    ?public String getAuthor() {
    ??return (this.author);
    ?}
    ?public void setName(String name){
    ??this.name=name;
    ?}?
    ?public String getName(){
    ??return this.name;
    ?}
    }
    簡單的,我們要實例化一個對象,然后clone此對象,注意,是clone!

    package com.denny_blue.dozerdemo;
    import net.sf.dozer.util.mapping.DozerBeanMapper;
    import java.util.List;
    import java.util.ArrayList;


    public class MyFirstDozerDemo {
    ?public static void main(String args[]){
    ??Book book1=new Book();
    ??book1.setAuthor("dennis");
    ??book1.setName("dozer demo");
    ??DozerBeanMapper mapper=new DozerBeanMapper();
    ??Book book2=new Book();
    ??mapper.map(book1,book2);
    ? book2=(Book)mapper.map(book1,com.denny_blue.dozerdemo.Book.class);
    ??System.out.println("book2's name:"+book2.getName());
    ?????}
    }?

    OK,如此簡單,我們把book1的屬性完全復制給了book2,兩者現在是完全獨立的對象??扇绻麅H僅是這樣,我們用BeanUtils不是也很容易辦到? book2=(Book)BeanUtils.cloneBean(book1);可如果我要把book1映射給一個完全不同的類的對象怎么辦?而且他們的屬性名也不相同,怎么辦?比如,一個CookBook類:

    package com.denny_blue.dozerdemo;
    public class CookBook {
    ?private String bookName;
    ?private String author;


    ?public CookBook(){}
    ?public String getBookName() {
    ??return (this.bookName);
    ?}

    ?public void setBookName(String bookName) {
    ??this.bookName = bookName;
    ?}

    ?public String getAuthor() {
    ??return (this.author);
    ?}

    ?public void setAuthor(String author) {
    ??this.author = author;
    ?}


    }
    它的bookName屬性與Book的name屬性名不一樣,我們該如何復制?dozer通過xml文件的配置來靈活地達到這個目的。我們配置一個dozerBeanMapping.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mappings PUBLIC "-//DOZER//DTD MAPPINGS//EN"
    "<mappings>
    <configuration>
    <stop-on-errors>false</stop-on-errors>
    <date-format>MM/dd/yyyy HH:mm</date-format>
    <wildcard>true</wildcard>
    </configuration>
    <mapping>
    <class-a>com.denny_blue.dozerdemo.Book</class-a>
    <class-b>com.denny_blue.dozerdemo.CookBook</class-b>
    <field>
    <a>name</a>
    <b>bookName</b>
    </field>
    <field>
    <a>author</a>
    <b>author</b>
    </field>
    </mapping>
    </mappings>

    如上所示,<class-a>指定所要復制的源對象,<class-b>復制的目標對象,<a>源對象的屬性名, <b>目標對象的屬性名。wildcard默認為true,在此時默認對所有屬性進行map,如果為false,則只對在xml文件中配置的屬性進行map。此時的demo 看起來像這樣:

    package com.denny_blue.dozerdemo;
    import net.sf.dozer.util.mapping.DozerBeanMapper;
    import java.util.List;
    import java.util.ArrayList;


    public class MyFirstDozerDemo {
    ?public static void main(String args[]){
    ??Book book1=new Book();
    ??book1.setAuthor("dennis");
    ??book1.setName("dozer demo");
    ??DozerBeanMapper mapper=new DozerBeanMapper();
    ? book2=(Book)mapper.map(book1,com.denny_blue.dozerdemo.Book.class);
    ? CookBook cookBook=new CookBook();
    ? List myMappingFiles = new ArrayList();
    ? myMappingFiles.add("dozerBeanMapping.xml");
    ? mapper.setMappingFiles(myMappingFiles);
    ? cookBook=(CookBook)mapper.map(book1,CookBook.class);
    ? System.out.println("cookBook's name:"+?? cookBook.getBookName()+"???? cookBook's author:"+
    ????????????????????? cookBook.getAuthor());
    ?}
    }

    通過mapper.setMappingFiles()設置映射文件,可以添加多個配置文件,也可以把所有的映射寫在一個配置文件里面。??更多復雜例子請見它自帶的doc。

    posted @ 2007-02-06 12:45 dennis 閱讀(2530) | 評論 (0)編輯 收藏

    最近重新再看<Inside JVM>,對JAVA編譯成的字節碼結構很感興趣,希望找個工具能夠對.class文件進行的解析和查看。沒找到,倒發現javaassist可以對字節碼進行操作和修改。此工具是JBOSS項目的一部分,JBOSS實現AOP的基礎。呵呵,開眼界了,原來我們可以直接對字節碼文件進行修改,哪怕不知道源文件(跟反編譯完全不同)。一個簡單例子:

    import javassist.*;
    class Hello {
    ??? public void say() {
    ??????? System.out.println("Hello");
    ??? }
    }

    public class Test {
    ??? public static void main(String[] args) throws Exception {
    ??????? ClassPool cp = ClassPool.getDefault();
    ??????? CtClass cc = cp.get("Hello");
    ??????? CtMethod m = cc.getDeclaredMethod("say");
    ??????? m.setBody("{System.out.println(/"shit/");}");
    ??????? m.insertBefore("System.out.println(/"fuck/");");
    ??????? Class c = cc.toClass();
    ??????? Hello h = (Hello)c.newInstance();
    ??????? h.say();
    ??? }
    }

    編譯運行此文件,輸出:

    fuck

    shit

    我們在

    ?CtMethod m = cc.getDeclaredMethod("say");
    ? m.setBody("{System.out.println(/"shit/");}");

    ? m.insertBefore("System.out.println(/"fuck/");");

    修改了say()方法,改成了

    System.out.println("fuck");

    System.out.println("shit");

    這里的ClassPool是CtClass的容器,它讀取class文件,并根據要求保存CtClass的結構以便日后使用,默認狀態下是從當前的類裝載器獲得,當然你可以指定:

    pool.insertClassPath("/usr/local/javalib");

    當然,不僅僅是修改方法,你還可以新建一個class,利用makeClass()方法,如:

    ClassPool pool = ClassPool.getDefault();
    CtClass cc = pool.makeClass("Point");

    還可以新增方法,下面是sample里的一個例子,同樣的:

    package sample;

    import javassist.*;
    import java.lang.reflect.*;

    /*
    ?? A very simple sample program

    ?? This program overwrites sample/Test.class (the class file of this
    ?? class itself) for adding a method g().? If the method g() is not
    ?? defined in class Test, then this program adds a copy of
    ?? f() to the class Test with name g().? Otherwise, this program does
    ?? not modify sample/Test.class at all.

    ?? To see the modified class definition, execute:

    ?? % javap sample.Test

    ?? after running this program.
    */
    public class Test {
    ??? public int f(int i) {
    ??? ?i++;
    ?? ?return i;
    ??? }

    ??? public static void main(String[] args) throws Exception {
    ?ClassPool pool = ClassPool.getDefault();

    ?CtClass cc = pool.get("sample.Test");
    ?Test test=new Test();
    ?Class c=test.getClass();
    ?Method []method=c.getDeclaredMethods();
    ?for(int i=0;i<method.length;i++){
    ??System.out.println(method[i]);
    ?}
    ?try {
    ???? cc.getDeclaredMethod("g");
    ???? System.out.println("g() is already defined in sample.Test.");
    ?}
    ?catch (NotFoundException e) {
    ???? /* getDeclaredMethod() throws an exception if g()
    ????? * is not defined in sample.Test.
    ????? */
    ???? CtMethod fMethod = cc.getDeclaredMethod("f");
    ???? CtMethod gMethod = CtNewMethod.copy(fMethod, "g", cc, null);
    ???? cc.addMethod(gMethod);
    ???? cc.writeFile();?// update the class file
    ???? System.out.println("g() was added.");
    ?}
    ??? }
    }
    第一次運行時,因為Test里并沒有g()方法,所以執行

    ?CtMethod fMethod = cc.getDeclaredMethod("f");
    ???? CtMethod gMethod = CtNewMethod.copy(fMethod, "g", cc, null);? //把f方法復制給g
    ???? cc.addMethod(gMethod);
    ???? cc.writeFile();?//更新class文件

    ???? System.out.println("g() was added.");
    打印:g() was added

    第2次運行時,因為以上步驟已經在class文件中增加了一個g方法,所以

    ?System.out.println("g() is already defined in sample.Test.");
    打?。篻() is already defined in sample.Test

    ?

    Javassist不僅能修改你自己的class文件,而且可以同樣修改JDK自帶的類庫(廢話,類庫也是人寫的^_^)具體請看它的tutorial。

    posted @ 2007-02-06 12:44 dennis 閱讀(803) | 評論 (0)編輯 收藏

    一般網站在處理用戶上傳圖片時通常采用兩種策略:一是直接把圖片存入數據庫中的Blob字段;二是數據庫中只存儲圖片的在服務器上的路徑信息?,圖片存放在分門別類的文件中,使用的時候從數據庫讀取路徑信息到頁面img元素即可.在此不討論兩種方案的優劣,我只是寫了個hibernate的例子來實現第一種策略.例子很簡單,t_user表主要兩個字段,name和photo,其中photo字段類型為Blob.在此例中數據庫我采用mysql, oracle的Blob字段比較特殊,你必須自定義類型,具體的請自行搜索,這方面的資料很多.

    //User.java  

    package com.denny_blue.hibernate;

    import java.io.Serializable;
    import java.sql.Blob;

    public class User implements Serializable{
    ?private Integer id;
    ?private String name;
    ?private Blob photo;
    ?/**
    ? * @return the id
    ? */
    ?public User(){
    ?}
    ?public Integer getId() {
    ??return id;
    ?}
    ?/**
    ? * @param id the id to set
    ? */
    ?public void setId(Integer id) {
    ??this.id = id;
    ?}
    ?/**
    ? * @return the name
    ? */
    ?public String getName() {
    ??return name;
    ?}
    ?/**
    ? * @param name the name to set
    ? */
    ?public void setName(String name) {
    ??this.name = name;
    ?}
    ?/**
    ? * @return the photo
    ? */
    ?public Blob getPhoto() {
    ??return photo;
    ?}
    ?/**
    ? * @param photo the photo to set
    ? */
    ?public void setPhoto(Blob photo) {
    ??this.photo = photo;
    ?}
    ?
    }

    類User有3個屬性,id,name,photo,相應的getter和setter方法以及一個無參構造函數.應該注意的是photo的類型java.sql.Blob

    相應的user.hbm.xml應該如下:

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC
    ?"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    ?"<hibernate-mapping
    ?package="com.denny_blue.hibernate">

    ?<class name="com.denny_blue.hibernate.User"
    ??????? table="t_user"
    ??????? dynamic-update="true"
    ??????? dynamic-insert="true"
    ??????? batch-size="3">
    ??<id name="id"
    ????? column="id"
    ????? type="java.lang.Integer">
    ???<generator class="native"/>
    ??</id>
    ??<property name="name" column="name" type="java.lang.String" lazy="true"/>
    ??<property name="photo" column="photo" type="java.sql.Blob"/>

    ?</class>

    </hibernate-mapping>

    對應的hibernate.cfg.xml配置文件,不再列出,請參照hibernate文檔自行設定.

    OK,做了這一步,我們寫個測試類來進行單元測試:

    package com.denny_blue.test;

    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.sql.Blob;

    import org.hibernate.Hibernate;
    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;

    import com.denny_blue.hibernate.User;

    import junit.framework.TestCase;

    public class HibernateTest extends TestCase {
    ??????? private Session session;
    ?protected void setUp() throws Exception {
    ??try{
    ???Configuration config=new Configuration().configure();
    ???SessionFactory sf=config.buildSessionFactory();
    ???session=sf.openSession();
    ??}catch(HibernateException e){
    ???e.printStackTrace();
    ??}
    ?}

    ?protected void tearDown() throws Exception {
    ??try{
    ???session.close();
    ??}catch(HibernateException e){
    ???e.printStackTrace();
    ??}
    ?}
    ?
    ?public void testSave()throws FileNotFoundException,IOException{
    ??User user=new User();
    ??user.setName("jordan");
    ??FileInputStream in=new FileInputStream("C://test.gif");
    ??Blob photo=Hibernate.createBlob(in);
    ??user.setPhoto(photo);
    ??Transaction tx=null;
    ??try{
    ??tx=session.beginTransaction();
    ??session.saveOrUpdate(user);
    ??tx.commit();
    ??}catch(HibernateException e){
    ???if(tx!=null)
    ????tx.rollback();
    ???e.printStackTrace();
    ??}finally{
    ???in.close();
    ??}
    ?}
    ?public void testLoad()throws Exception{
    ??try{
    ???User user=(User)session.load(User.class, new Integer(1));
    ???Blob photo=user.getPhoto();
    ???InputStream in=photo.getBinaryStream();
    ???FileOutputStream out=new FileOutputStream("C://out//test2.gif");
    ???byte [] buf=new byte[1024];
    ???int len;
    ???while((len=in.read(buf))!=-1){
    ????out.write(buf, 0, len);
    ???}
    ???in.close();
    ???out.close();
    ??}catch(HibernateException e){
    ???e.printStackTrace();
    ??}
    ?}

    }
    我們讀取C盤目錄下的test.gif并存儲到數據庫中,然后再取出來寫入C:/out目錄,此時你可以查看下數據表中photo顯示為blob,表示已經成功存入.值的注意的代碼片段就是:

    FileInputStream in=new FileInputStream("C://test.gif");
    ??Blob photo=Hibernate.createBlob(in);
    我們這里是從磁盤中讀取圖片,實際應用中你可以利用上傳組件得到圖片的2進制數據流,并利用Hibernate.createBlob方法來構造相應的Blob對象.而取圖片則使用

    InputStream in=photo.getBinaryStream();

    這只是個簡單的測試類,如果我想從數據庫中取出圖片并現實在頁面上該如何做呢?其實也很簡單,我們先要寫一個servlet,在它的service方法中取出圖片,并"畫"到指定頁面上.

    package com.easyjf.asp.action;

    import java.io.InputStream;
    import java.io.OutputStream;
    import java.sql.Blob;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    import com.denny)blue.hibernate.User;


    public class Test extends HttpServlet {

    ?/**
    ? * Destruction of the servlet. <br>
    ? */
    ?private Session session;
    ?public void destroy() {
    ??try{
    ???session.close();
    ??}catch(HibernateException e){
    ???e.printStackTrace();
    ??}
    ?}

    ?/**
    ? * Initialization of the servlet. <br>
    ? *
    ? * @throws ServletException if an error occure
    ? */
    ?public void init() throws ServletException {
    ??try{
    ???Configuration config=new Configuration().configure();
    ???SessionFactory sf=config.buildSessionFactory();
    ???session=sf.openSession();
    ??}catch(HibernateException e){
    ???e.printStackTrace();
    ??}
    ?}
    ??? public void doGet(HttpServletRequest request,HttpServletResponse response)
    ??? {
    ??? ?try{
    ???User user=(User)session.load(User.class, new Integer(1));
    ???Blob photo=user.getPhoto();
    ???InputStream in=photo.getBinaryStream();
    ???OutputStream out=response.getOutputStream();
    ???byte [] buf=new byte[1024];
    ???int len;
    ???while((len=in.read(buf))!=-1){
    ????out.write(buf, 0, len);
    ???}
    ???in.close();
    ???out.close();
    ??}catch(Exception e){
    ???e.printStackTrace();
    ??}
    ??? }

    }

    通過response.getOutputStream取得輸出流,其他就與上段代碼一致.servlet寫好了,怎么在頁面調用呢?那就更簡單啦,直接在頁面的img標簽的src屬性上調用該servlet即可,如:

    <img id="test" src="/servlet/Test"/>

    ?

    簡單的例子,希望對初學者有幫助.

    附記:如果不希望在servlet(或者action之類)中進行保存操作,希望在DAO進行此操作,那么InputStream的關閉問題可以通過hibernate的interceptor機制解決

    posted @ 2007-02-06 12:43 dennis 閱讀(485) | 評論 (0)編輯 收藏

    僅列出標題
    共56頁: First 上一頁 48 49 50 51 52 53 54 55 56 下一頁 
    主站蜘蛛池模板: 91亚洲国产成人久久精品网址| 久久久精品免费国产四虎| 亚洲av永久无码精品国产精品 | 亚洲日产韩国一二三四区| 免费人成视频在线| 日韩免费在线观看视频| 一级大黄美女免费播放| 色婷婷亚洲一区二区三区| 亚洲二区在线视频| 亚洲自偷自偷精品| 亚洲精品色午夜无码专区日韩| 免费A级毛片无码久久版| 猫咪社区免费资源在线观看| 18女人毛片水真多免费| 国产日韩一区二区三免费高清| 污视频网站在线观看免费| 亚洲精品9999久久久久无码| 亚洲国产成人久久77| 91嫩草私人成人亚洲影院| 国产亚洲综合久久系列| 亚洲中文字幕视频国产| 成人亚洲网站www在线观看| 精品国产免费观看久久久| 中文字幕无码免费久久99| 91成人免费观看网站| xxxxwww免费| 99久久99久久精品免费看蜜桃 | 久久亚洲AV午夜福利精品一区| 亚洲综合色成在线播放| 亚洲精品视频久久久| 亚洲国产成人久久一区久久| 免费国产成人高清在线观看麻豆 | 亚洲国产精品综合久久久| 99久久精品国产亚洲| 久久久久亚洲av无码专区| 亚洲一区二区三区高清| 中文字幕亚洲色图| 亚洲中文无码av永久| 国产精品亚洲综合五月天| 亚洲国产成人久久综合| 国产成人高清亚洲一区久久|