2017年12月27日 星期三

Java Spring - Caching Data

  • Cache
    • 如果問題的答案不會那麼頻繁變更,那麼使用相同方式一遍遍去獲得就是一種浪費
    • 可能還會對performance產生負面影響
    • Caching可以store經常會用到的information
  • Enabling cache support
    • 可使用annotation-driven的方式,或是XML

Java Spring - Persisting data with object-relational mapping

  • 在persisting data中,JDBC就像自行車,對於份內的工作能夠很好地完成並且在一些特定場合表現出色;但隨著application越來越複雜,需求也變得複雜
    • 我們需要將object的property mapping到database上
    • 需要自動生成query, statement
    • 可以不用再寫問號
      • lazy loading: 允許在需要的時候獲得data
      • eager fetching: 與lazy loading相對。預先取得,可藉由一個操作將全部從db取出,節省多次查詢的成本
      • cascading: 關聯刪除。
    • 一些可用的framework提供這樣的服務。這些服務的通用名稱是object-relational mapping, ORM
    • 在persistent layer使用ORM,可以節省數千行的code和大量的開發時間
    • ORM可以把你的注意力從容易出錯的SQL轉向如何實現應用程序的真正需求
    • Spring對不同的ORM的support很類似。一旦掌握其中一種對ORM的support,可以很輕鬆的切換到另一種framework 

Java Spring - Spring JDBC

  • Spring data-access
    • Spring的目標之一就是允許在開發的時候,能夠遵循OO原則中的coding to interface。Spring對data的support也是如此
    • 為了避免persistence logic分散到各個component,最好將data access放到一個或多個專注在此任務的component中
    • 這樣的component通常稱為data access object, DAO或repository
    • 為了避免application和特定的data access strategy,良好多repository應該要用interface的方式顯示功能
      • service object ---> repository interface <--- repository implementation
    • service object本身並不會處理data access,而是會將data access delegate給repository,repository interface確保和service object decoupling
      • 好處:service object好測試,因為不需要和特定的data access implementation綁在一起,也可以為這些interface建立mock implementation,無需連接DB就能夠測試service object
      • 只有data access相關的method才透過interface exposed。這可以實現靈活設計,且切換data-persistence framework對應用程式其他部分帶來影響最小。如果將細節滲透到application的其他部分,則整個application將和data access layer couple在一去,導致僵化的設計
    • interface&Spring: 
      • interface是實現low coupling的key,並且應將其應用在application的各個layer

2017年12月26日 星期二

Java Spring - 建立一個pizza flow


  • Define basic flow
    • State:
      • Start 
      • Identify Customer ->customerReady
      • buildOrder -> orderCreated
      • takePayment ->paymentTaken
      • saveOrder
      • thankCustomer
      • endState // end-state

Java Spring - Spring Web Flow


  • Spring Web Flow:
    • 是一個Web的框架,適用於元素按規定流程運行的process
    • Struts沒辦法將flow及implementation 分離,flow的定義分散在組成流程的各個元素中。沒有一個地方能透完整描述整個流程
    • Spring Web Flow是Spring MVC的extension,support基於流程的application,流程的定義及implement flow behavior的class及view能夠分開
    • 使用Spring Web Flow做一個pizza order web application

Java Spring - Carrying data across redirect requests

  • redirect
    • 處理完POST後,通常都會執redirect。這樣能夠防止點擊refresh或back時,client重新執行危險的POST
    • 通常使用redirect: prefix能夠重新定位
    • return "redirect:/spitter/" + spitter.getUsername();
      
    • 問: 如何發送data給redirect的目標method?
    • 答: 當一個controller method完成之後,這個method所指定的model data將會複製到request中,並作為request的property,request會forward到view上。因為controller method和view處理的是同一個request,所以在forward過程中,request property也能夠保存。但當controller是redirect時,原始的request就消失了,並且會發起一個新的GET request。原始request中所帶有的model data也跟著request消失了,在新的request上,沒有任何的model data,這個request必須要自己計算data
    • 有一些方法能夠使用redirect但又能夠將data傳遞給redirect的method中
      • 使用URL template 以path variable或或query parameter的形式
      • 透過flash attribute發送data

Java Spring - Handling exceptions


  • Exception
    • 如果在request processing的時候出現exception,則outcome依然是Servlet response。
    • exception需要以某種方式被轉換成response
    • Spring提供多種方式將exception轉換為response
      • 特定的Spring exception將會自動mapping成指定的HTTP status code
      • Exception上可以加@ResponseStatus annotation,從而將其mapping為某一個HTTP status code
      • method上可以加上@ExceptionHandler,使其用來處理exception
  • 將exceptions mapping至HTTP status codes
    • default情況下,Spring會將自身的一些exception轉換成合適的status code
      • BindException 400 Bad Request
      • ConversionNotSupportedException 500 Internal Server Error
      • HttpMediaTypeNotAcceptableException 406 Not Acceptable
      • HttpMediaTypeNotSupportedException 415 Unsupported Media Type
      • HttpMessageNotReadableException 400 Bad Request
      • HttpMessageNotWritableException 500 Internal Server Error
      • HttpRequestMethodNotSupportedException 405 Method Not Allowed
      • MethodArgumentNotValidException 400 Bad Request
      • MissingServletRequestParameterException 400 Bad Request
      • MissingServletRequestPartException 400 Bad Request
      • NoSuchRequestHandlingMethodException 404 Not Found
      • TypeMismatchException 400 Bad Request
    • 例如,如果DispatcherServlet無法找到適合處理request的controller method,則會拋出NoSuchRequestHandlingMethodException,最終結果就是產生404 status code response
    • Spring提供一個機制,能夠透過@ResponseStatus annotation將exception mapping為HTTP status code
    • 範例: 
    • @RequestMapping(value="/{spittleId}", method=RequestMethod.GET)
      public String spittle(@PathVariable("spittleId") long spittleId, Model model) {
        Spittle spittle = spittleRepository.findOne(spittleId);
        if (spittle == null) {
          throw new SpittleNotFoundException();
        }
        model.addAttribute(spittle);
        return "spittle";
      }
      
    • 如果findOne返回null,就會throw SpittleNotFoundException exception,且response code為500。實際上,如果出現任何沒有mapping的exception,response都會是500 status code。
    • mapping
      • SpittleNotFoundException是一種資源沒找到的異常,其實HTTP404是比較精確的response status code。所以,要使用@ResponseStatus將SpittleNotFoundException mapping至HTTP404
      package spittr.web;
      import org.springframework.http.HttpStatus;
      import org.springframework.web.bind.annotation.ResponseStatus;
      @ResponseStatus(value=HttpStatus.NOT_FOUND,
                      reason="Spittle Not Found") //將exception mapping至404
      public class SpittleNotFoundException extends RuntimeException {
      }
      
  • Exception handling method
    • 如果想要response不僅包含status code,還要包含產生的錯誤,此時就不能將exception視為HTTP error,而是要按照處理request的方式來處理exception
    • 假設使用者新增的Spittle和已存在的Spittle相同,SpittleRepository的save()將會拋出DuplicateSpittleException
    • 這表示SpittleController的saveSpittle() method需要處理這個exception
    • @RequestMapping(method=RequestMethod.POST)
      public String saveSpittle(SpittleForm form, Model model) {
        try {
          spittleRepository.save(
              new Spittle(null, form.getMessage(), new Date(),
                  form.getLongitude(), form.getLatitude()));
          return "redirect:/spittles";
        } catch (DuplicateSpittleException e) {
           return "error/duplicate";
        }
      }
      
    • 如果能夠讓saveSpittle() method只關注在正確的path,而讓其他method處理exception,也許能夠簡單一點
      • 先將saveSpittle() method的exception handler移除(易理解及測試,因為只有一個path)
      • @RequestMapping(method=RequestMethod.POST)
        public String saveSpittle(SpittleForm form, Model model) {
          spittleRepository.save(
              new Spittle(null, form.getMessage(), new Date(),
                  form.getLongitude(), form.getLatitude()));
          return "redirect:/spittles";
        }
        
      • 為SpittleController添加一新的method,會處理DuplicateSpittleException的情況,這和處理request是一致的
      • @ExceptionHandler(DuplicateSpittleException.class)
        public String handleDuplicateSpittle() {
          return "error/duplicate";
        }
        
    • 對於@ExceptionHandler來說,他能夠處理同一個controller所有method拋出的DuplicateSpittleException exception,而不需要在每一個可能拋出DuplicateSpittleException的method中增加handle code
  • Advising controllers
    • 如果controller class特定的aspect能夠運用到整個application的所有controller,這會很方便
    • 如果多個controller都會拋出某個特定的exception,可能會發現要在所有controller重複相同的@ExceptionHandler
    • 為了避免重複,可以create一個base controller,所有controller都extends這個class,從而extends common @ExceptionHandler
    • Spring3.2 introduce一個新的解決方案: controller advice,是任意帶有@ControllerAdvice的class,這個class會包含一個或多個下面annotation的method,且會運用到整個application中的所有controller中帶有@RequestMapping的method上
      • @ExceptionHandler
      • @InitBinder
      • @ModelAttribute
    • @ControllerAdvice本身已經使用了@Component因此@ControllerAdvice所標註的class將會自動被ComponentScanner掃描到,就像帶有@Component一樣
    • @ControllerAdvice主要用法:
      • 將所有的@ExceptionHandler method蒐集到一個class中,如此一來所有的exception就能在同一個地方進行一致的處理
      package spittr.web;
      
      import org.springframework.web.bind.annotation.ControllerAdvice;
      import org.springframework.web.bind.annotation.ExceptionHandler;
      
      @ControllerAdvice
      public class AppWideExceptionHandler {
          @ExceptionHandler(DuplicateSpittleException.class)
          public String duplicateSpittleHandler() {
              return "error/duplicate";
          }
      }
      
      • 如此一來,任意的controller method如果拋出了DuplicateSpittleException,都會使用duplicateSpittleHandler()來處理Exception

Java Spring - 處理圖片Multipart

  • 處理multipart format的data
    • 上傳文件,對應的部分可以是binary data
    •         ------WebKitFormBoundaryqgkaBn8IHJCuNmiW
              Content-Disposition: form-data; name="firstName"
              Charles
              ------WebKitFormBoundaryqgkaBn8IHJCuNmiW
              Content-Disposition: form-data; name="lastName"
              Xavier
              ------WebKitFormBoundaryqgkaBn8IHJCuNmiW
              Content-Disposition: form-data; name="email"
              charles@xmen.com
              ------WebKitFormBoundaryqgkaBn8IHJCuNmiW
              Content-Disposition: form-data; name="username"
              professorx
              ------WebKitFormBoundaryqgkaBn8IHJCuNmiW
              Content-Disposition: form-data; name="password"
              letmein01
              ------WebKitFormBoundaryqgkaBn8IHJCuNmiW
              Content-Disposition: form-data; name="profilePicture"; filename="me.jpg"
              Content-Type: image/jpeg
                [[ Binary image data goes here ]]
              ------WebKitFormBoundaryqgkaBn8IHJCuNmiW--
      
    • 在處理文件上傳以前,必須要先配置一個multipart resolver,透過此來告知DispatcherServlet該如何讀取multipart request

Java Spring - 使用其他方式設定DispatcherServlet及ContextLoaderListener

  •  透過其他方式set up DispatcherServlet and ContextLoaderListener
    • 可能需要額外的Servlet、filter
    • 需要對DispatcherServlet做額外config
  • 自行定義個DispatcherServlet configuration
    • 除了以下三種必須被override的method以外,其實還有更多可以被override的method
      • getRootConfigClasses
      • getServletConfigClasses
      • getServletMappings

Java Spring - Rending Web View

  • Spring resolver
    • 將controller中請求處理的logic和view中render的implement decouple是Spring MVC的特性
    • 如果controller method直接產生HTML,很難在不影響request處理logic的前提下維護更新view
    • controller和view會在model的內容達成一致,這是最大關聯。除此之外,兩者應該保持距離
    • 而Spring resolver的重點功能就在於透過logic view name知道要使用哪過view render model

2017年12月25日 星期一

Java Spring - 搭建Spring MVC (2)

  • Accept request parameter
    • Spring MVC允許多種方式將client的data傳到controller method中
      1. Query parameter
      2. Form parameter
      3. Path variable
  • 處理Query parameter
    • 翻頁功能,讓使用者可以選擇要看哪一頁
    • 假設要查看某一頁的Spittle列表,則這個list會按照最新的Spittle在前進行排序,因此下一頁的第一筆ID早於前一頁的最後一筆ID
    • 為了顯示下一頁的Spittle,需要將一個Spittle的ID傳入
    • 也可以傳入一個parameter確定要展現的Spittle counts
    • 需要寫的controller method要處理以下參數
      • before parameter
      • count parameter
    • 將spittles() method替換為使用上述兩個parameter的新spittles() method

Java Spring - 搭建Spring MVC (1)

  • Spring MVC lifecycle request
  •  
    from Spring in action

      1. request進入1,會帶著URL, form submitted by user,.. 等資訊,此時會進入front controller servlet(DispatcherServlet)。DispatcherServlet任務是將request發送給Spring MVC controller,因此DispatcherServlet需要知道要發給誰。
      2. 所以DispatcherServlet會查詢一個或多個handler mapping來確定request的下一站在哪裡。handler mapping會根據request 所攜帶的URL來決定。
      3. 一但知道要送到哪一個controller,DispatcherServlet就會將request發送。到了controller,request會卸下其request並交給controller處理訊息。(設計良好的controller本身幾乎不處理工作,而是將業務邏輯delegate給一個或多個service objects處理)
      4. controller完成logic後會產生一些結果,這些結果需要返回給使用者在browser上顯示。這些資訊稱為model。這些model還會經過friendly方式格式化,通常是HTML。所以information需要給一個view呈現,通常稱為JSP。controller最後要做的一件事情就是將model data打包,並且知道哪個view需要呈現output。接著會將request連同model及view送回DispatcherServlet
      5. 這樣一來,controller就不會和view coupled,傳給DispatcherServlet的view name也不用特別標示為JSP。這個名字就是用來找產生真正結果的view。DispatcherServlet會使用ViewResolver來將view name mapping為特定一個的view implementation。
      6. 最後一站是view的implementation。在這它交付model data。request的任務也完成了。view使用model data render output。這個output會被帶回給client

2017年12月24日 星期日

Java Spring - Spring AOP advice & AspectJ


  • 建立annotated aspects
    • AspectJ5的特性
    • 簡便的通過少量的annotation把任意class轉變為aspect
  • 定義aspect
    • 一場表演,觀眾很重要,但對演出功能本身而言,觀眾並不是必要。因此,在Performance上,觀眾是aspect,並將其應用到Performance
    • @Aspect
      public class Audience {
          @Before("execution(** concert.Performance.perform(..))") //perform()之前
          public void silenceCellPhones() {
              System.out.println("Silencing cell phones");
          }
      
          @Before("execution(** concert.Performance.perform(..))") //perform()之前
          public void takeSeats() {
              System.out.println("Taking seats");
          }
      
          @AfterReturning("execution(** concert.Performance.perform(..))") //perform()成功執行後
          public void applause() {
              System.out.println("CLAP CLAP CLAP!!!");
          }
      
          @AfterThrowing("execution(** concert.Performance.perform(..))") //表演失敗之後
      
          public void demandRefund() {
              System.out.println("Demanding a refund");
          }
      }
      

Java Spring - 透過pointcut選擇join points


  • 透過pointcut選擇join points
    • advice及pointcut是aspect的最基本元素
    • 在Spring AOP中,要使用AspectJ的pointcut expression language定義pointcut
    • Spring僅支援AspectJ pointcut designator的子集,如下
      • arg()
      • @args()
      • execution()
      • this()
      • target
      • @target()
      • within()
      • @within()
      • @annotation

2017年12月22日 星期五

Java Spring - AOP基本概念


  • 散佈在application多處的功能(如log, security, cache,...)被稱為cross-cutting concern
  • 這些cross-cutting concern概念上通常會和業務邏輯分開,但往往又會直接嵌入到業務邏輯中
  • 將這些cross-cutting concern和業務邏輯分離,正是AOP要解決的事情
    • DI: Application object之間的decoupling
    • AOP: cross-cutting concern和他們影響的object之間的decoupling
  • AOP是什麼?
    • Aspect oriented programming
    • 能夠協助將cross-cutting concern模組化,如下圖為橫切服務的功能
    • from spring in action 4
    • 問題:若要使用相同的功能,通常使用inheritance, delegation
      • inheritance: 若整個application都使用同一個base class,會導致脆弱的object
      • delegate:需要對delegate對象進行複雜的呼叫
    • 解法:
      • AOP取代inheritance及delegate,且在很多場景下都簡潔
      • 需要定義common functionality
      • 可以定義function需要在哪裡被應用,不需要修改受影響的class
      • cross-cutting concern可以被模組化成特殊的class,這些class稱為aspect
    • 優勢:
      • 每個concern都集中在同一個地方,而不是散到程式碼各處
      • 主要的service module更簡潔,因為程式碼只包含主要的concern code,次要的concerns被轉移到aspects
  • 定義AOP term
    • advice (抄電表員紀錄用電量:工作)
      • aspects的工作就叫做advice
      • advice定義了aspects是什麼,且什麼時候使用
      • 什麼時候使用:比如某個method前?後?前後都call?threw exception時用?
      • Spring aspects可以使用五種type advices
        1. Before: target method前
        2. After: target method後
        3. After-returning: target method successfully 完成
        4. After-throwing: target method拋出exception的時候
        5. Around: advice wraps advice methods,在被通知的method call之前和之後執行自己定義的function
    • join point (抄電表員目標就是房屋內那些安裝的電表)
      • application執行過程中能夠insert join point的點
      • join point可以是call method, throw exception,甚至是修改string
      • aspect能夠insert join point到正常流程中,加入新的行為
    • pointcut (抄電表員工作的範圍應該是有指定區域的)
      • advice定義what&when,pointcut定義where
      • 匹配advice所有織入(woven)的join cut
      • 有些AOP framework允許創立dynamic pointcut,可以在runtime的時候決定是否apply advice
    • aspect (抄電表員知道完成工作所需要的所有東西)
      • advice與point cut的結合(what, where, when)
    • introduction
      • 可以將現有的ass加入新的method或property
    • weaving
      • aspect應用到target object並且創建新的proxy object的過程
      • 在指定的join cut被weaving到target object
      • 在target object可以有很多點進行weaving
        • compile time: target class compile的時候被weaving,需要特殊的compiler如AspectJ
        • class load time: target class被load到JVM的時候被weaving,需要特殊的class loader,AspectJ5的load-time weaving(LTW) support
        • runtime: target class在runtime時weaving。一般情況下,weaving時AOP container會為target object dynamic創建一個proxy object。而Spring AOP就是這種方式
  • Spring對AOP的support
    • AOP framework基本功能:建立pointcuts,定義join points在哪個aspects需要被woven
    • Spring提供四種type的AOP support
      1. classic Spring proxy-based AOP
      2. Pure-POJO aspects: 需要使用XML,藉由aop namespace轉換POJO為aspects
      3. @AspectsJ: 可以不使用XML
      4. Injects AspectJ aspects: APO需求當不只有constructor, property的使用時,可以使用aspects implements AspectJ
  • Spring advice是Java寫出來的
    • 定義advice用的pointcut通常會使用annotation或在Spring config file裡使用XML編寫
    • AspectJ是以Java擴展的方式implement
      • 優點:可以獲得更強大的控制
      • 缺點:需要學期額外的新工作及語法
  • Spring通知objects at runtime
  • Spring only supports method join points
    • 因為Spring是基於dynamic proxy,所以Spring指支援method的join points
    • 如AspectJ, JBoss還提供field及constructor join points(因此Spring無法再bean create的時候使用advice)
    • method join points可以滿足絕大部分的需求

2017年12月21日 星期四

Java Spring - Scoping beans


  • Bean
    • 默認情況下,Spring application context所有的bean都是singleton(只有一個instance),也就是不管一個bean被injects多少次,都是同一個instance
    • 問題:
      • 有些application中,object使用stateless可能不太合理
      • 有些時候某些object是mutable(狀態會變),所以會有一些state,因此reuse不安全,這個時候class若是singleton bean就會有問題
    • Spring定義了bean的scope:
      1. Singleton: 整個application只會建立一個instance (default)
      2. Prototype: 每次injects或是透過Spring application context get時都會建一個新的bean instance
      3. Session: Web application中,為每個session創建一個bean instance
      4. Request: Web application中,為每個request創建一個bean instance

Java Spring - Conditional beans


  • Conditional beans
    • 需求:
      • 在某些條件的成立下,此bean才被create,比如某個特定的environment variable被設置以後才create bean
    • 解法:
      • Spring4以後引入一個新的@Conditional annotation -> 若給定的條件成回傳為true,則會create這個bean,否則會被忽略

Java Spring - Configuring profile beans


  • 在開發環境中,遷移是一個挑戰(比如Dev->QA, QA->Prod)
    • 假設有個DB config,在Dev上可能使用的是EmbeddedDatabaseBuilder
    • @Bean(destroyMethod="shutdown")
      public DataSource dataSource() {
          return new EmbeddedDatabaseBuilder()
             .addScript("classpath:schema.sql") //schema會定義在schema.sql中
             .addScript("classpath:test-data.sql")//data使用test-data.sql載入
             .build();
      }
      

2017年12月20日 星期三

Java Spring - Mixing configurations

  • Importing & mixing configurations混搭
    • autowired會考慮所有container中的bean,不論是在JavaConfig、XML或是@CompnentScan

Java Spring - 使用Java configuration或XML設置config


  • Wiring bean with Java
    • 建議使用@Component及@Autowired
    • 問題
      • 將3rd party library的component做autowired到application,這種時候就無法在3rd-party的class上加上@Component及@Autowired
    • 解法
      • 採用顯示configuration。可以使用Java或XML

Java Spring - Automatically wiring beans

  • 創造application中DI本質的行為稱為wiring
  • Spring configuration options
    • Spring container負責創建application中的bean。並且通過DI協調之間的關西
    • 需要告訴Spring哪些bean如何將其wiring在一起
    • wiring mechanisms(選擇方式可以互相搭配)
      1. 顯式在XML中配置 (最末)
      2. 顯式在JAVA中配置 (次之)
      3. 隱式的bean自動wiring及discovery (盡可能使用)

Java Spring - Application context及Bean生命週期


  • Spring致力於簡化企業級的Java開發,low coupling,關鍵在於DI及AOP
  • Bean
    • Spring container負責create對象,wired,configured並管理他們的生命週期(new()~finalize())
    • Container是Spring framwork的核心,使用DI管理組件,因此會簡單乾淨,容易理解。更重要的是,容易進行unit test
    • Spring container可歸為兩種不同類型:
      • bean factory: (org.springframework.beans.factory.BeanFactory interface)提供基本DI support,對大多數應用來說太low-level
      • application context: (org.springframework.context.ApplicationContext interface)基於bean factory建置,提供application框架級的服務

2017年12月19日 星期二

Java Spring - DI, AOP, Boilerplate Code核心概念


Spring:
簡單的JavaBean實現EJB才能完成的事情
解決企業級應用開發的複雜性創建,簡化JAVA開發
  1. 基於POJO的輕量級和最小侵入性coding
  2. 通過DI AOP
  3. 基於切面和慣例進行聲明式coding
  4. 透過切面和模板減少樣板式coding

2017年12月13日 星期三

HTML CSS (9) - 其他設計概念


  • CSS權重問題
    • 先看權重
      • html: 1分
      • 自行命名class: 10分
      • id: 100分 (在css內為井號在前#id)
      • style在內:1000分
      • !important: 10000分 css內直接寫!important
        • p(1分)
        • .header(10分)
        • .header p (11分)
        • .header .menu li (21分)
    • 後面覆蓋前面
  • 開發前思考結構
    • 先命名class
  • head tag
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <meta description="keywords" content="新聞、電子信箱和搜尋功能只是起點。每天發掘更多精彩內容。打造專屬自我的 Yahoo奇摩體驗。"> // 網站描述文字
    <meta name="keywords" content="yahoo, yahoo奇摩, yahoo奇摩首頁, yahoo首頁, yahoo搜尋, yahoo 信箱, yahoo 即時通訊, 新聞, 股市, 運動, 娛樂, 拍賣, 購物中心, 超級商城">// 關鍵字可以找得到,中間用逗號分隔
    <meta property="og:title" content="Yahoo奇摩" /> // FB嵌入使用
    <meta property="og:type" content='website' />
    <meta property="og:url" content="http://tw.yahoo.com" />
    <meta property="og:image" content="https://s.yimg.com/dh/ap/default/130909/y_200_a.png"/>
    <meta property="og:site_name" content="Yahoo奇摩" />
    <meta http-equiv="X-UA-Compatible" content="chrome=1"> //針對 IE 做相容性
    <link rel="shortcut icon" href="https://mbp.yimg.com/sy/rz/l/favicon.ico"> // 網頁tab上的icon
<link rel="stylesheet" href="css/maruko8.css"> // 先css再JS </head>


  • 設計注意事項
    • 少用position = absolute
    • 多用互動性設計(如hover, focus)
    • 權重須標示清楚,如ul li h1, ...
    • 整個版面都相同的設定,如文字大小,css可在body內設定
    • 網頁結構越乾淨越好,不要加入太多標籤
    • class名稱儘量有意義

2017年12月12日 星期二

HTML CSS (8) - 表格及表單


  • Table
<table>
    <tr>
     <th>2017/12/01</th>
    <th>クリスマス&大みそか原作スペシャル」で 1996年送の人気エピソードをリメイク!</th>
    </tr>
    <tr>
     <td>2017/11/22</td>
     <td>公式YouTube「ちびまる子ちゃんねる」開設記念!【ちびまる子ちゃん×まる</td>
    </tr>
    <tr>
     <td>2017/11/22</td>
     <td>相鉄ローゼンの年賀状印刷にて「ちびまる子ちゃん」デザインが注文できます!</td>
    </tr>
</table>

結果如下

HTML CSS (7) - 操作背景圖片


  • 置入背景圖片
    • 可使用background-image:url(相對路徑或絕對路徑)
.box{
 width: 200px;
 height: 200px;
 background-image: url("../img/rabbit.png")//注意目前位置在css資料夾
}

預設會重複

2017年12月8日 星期五

HTML CSS (6) - 相對定位及絕對定位


6-1 相對定位及絕對定位

  1. 相對定位position:absolute;
  2. 區塊內需寫position:absolute再定義位置
    • 左上  left:0 top:0
    • 左下  left:0 bottom:0
    • 右上  right:0 top:0
    • 右下  right:0 bottom:0
    .content{
     background: black;
     width:200px;
     height:200px;
     position:absolute; //絕對定位
     left: 0; //左下角
     bottom: 0;
    }
    .content2{
     background: red;
     width: 500px;
     height:200px;
     position:absolute; //絕對定位
     right:0; //右上角
     top:0;
    }
    
    • 黑區塊和紅區塊不會理會原本的配置,會被置放在絕對位置

2017年12月7日 星期四

HTML CSS (5) - 網頁排版

5-1 關於如何將兩個元素並排:

https://stackoverflow.com/questions/5759554/displayinline-resets-height-and-width/5759565#5759565
根據這篇可知道,inline attribute並沒有長寬,因此如果要使兩個元素有inline的效果,需要使用floatinline-block.

浮動效果float:會根據元素大小並排。若寬度比瀏覽器寬度長,則下一個元素會被推到下一層
float:left;往左靠
float:right; 往右靠

.box{
  width: 200px;
  height: 50px;
  background: black;
  float:left;
}
.box2{
  width: 200px;
  height: 50px;
 background: pink;
  float:left;
}

2017年12月6日 星期三

HTML CSS (4) - 使用CodePen


  1. 進入CodePen
  2. 點選右上角Create -> New Pen
  3. html, css皆可直接輸入(支援Emmet)
  4. 儲存
  5. 註冊後,即可取得網址分享給朋友



2017年12月4日 星期一

HTML CSS (3) - CSS排版設定

3-1 移除browser預設樣式




















default瀏覽器會設置樣式,如上圖的margin
若欲消除預設的樣式設定可在自訂link css reference內放入

body {
  margin: 0;
}

但也會有其他樣式會有css預設設定,因此可以使用此網頁將樣式貼入css
注意:css是從前讀到後面(意即後面的設定會覆蓋掉前面的設定

HTML CSS (2) - CSS介紹

2-1 CSS介紹及用途

html設計出的網頁文字顏色等能夠改變,設定樣式。
  1. 新增css資料夾
  2. 新增副檔名為css的檔案,如style.css
  3. 在html內的header中新增<link> tag
<head>
  <link rel="stylesheet" type="text/css" href="css/style.css">
</head>
  • rel: 定義該檔案和連結檔案的相對關係,css則需要設定為stylesheet
  • type:連結檔案的格式
  • href: 相對路徑的css檔
CSS可針對html標籤指定樣式 (注意要有中括號,內為屬性+冒號+value+分號
  • 針對h2標籤內的字體顏色做變化: color
  • 文字大小: font-size
1
2
3
4
h2{
  color: pink;
  font-size: 40px;
}

2017年12月3日 星期日

HTML CSS (1) - 環境及常用標籤

1-1 準備工作

下載以下兩個工具
  1. Sublime Text3
  2. 自動排版套件
  3. 安裝sublime package -> 安裝後command+shift+p可搜尋安裝Emmet
測試是否會自動產生html tag
  1. 將儲存格式選定為.html
  2. 輸入<html
  3. 按下tab
簡單建立一網頁
  1. 建立一資料夾,名為project
  2. 開啟sublime輸入test
  3. 存檔為html format,命名為index.html
  4. 至資料夾開啟此html

JSP-Servlet (4) - Container

Container:
  • Tomcat就是一個實作Container的範例
  • Container開機的時候,載入你寫的Servlet class並初始化
  • 當Apache(Web Server)收到針對動態網頁的request時,將會交由負責此servlet的Container處理
  • Container會將HttpServletRequest object & HttpServletResponse object交給Servlet thread
  • 呼叫執行Servlet的service()內doGet()或是doPost()的method(基於HTTP Request的method)
- HTTP server是用來服務HTTP
- Apache Tomcat是用來deploy Java Servlet, JSP。當Java project build成為WAR檔,就可以直接將此檔丟到Tomcat以便deploy。是用來服務Servlet&JSP Server

使用Container的五大項優點(因為以下的事項,更能夠集中精神專注於商業邏輯的開發)
  1. 與Web Server溝通取得request(因此不需要實作Listener, stream, ServerSocket...)
  2. 控制Servlet的生命週期,initialization, call method,... 適時的將instance GB。透過Container 則不需要擔心資源管理
  3. 當多個request進入時,Container會自行建立thread來處理此請求,當此servlet執行為service() method時,thread就會結束。但synchronize的事情還是得自己處理
  4. 可調整web.xml來設定哪些群組能夠讀取哪些網頁,是否需要login機制,welcome html page等寫在內,可以不透過修改Java程式達到這些目的
  5. 能夠將JSP轉成真實的Java檔案
Container處理HTTP request steps
  1. 使用者點擊非靜態網頁的超連結
  2. container收到後,建立HttpServletRequest object & HttpServletResponse object
  3. 根據web.xml之URL及真實Servlet位置對應找出此Servlet後,會將上述object交由Servlet thread
  4. 呼叫Servlet內的service(),且根據request method,service()執行呼叫doGet()或是doPost()
  5. thread產生的動態頁面,將會放入 HttpServletResponse object
  6. 因container保有此HttpServletResponse object的reference,所以能夠將此response轉換成HTTP response,接著刪除HttpServletRequest object & HttpServletResponse object
以下Servlet範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.*;
import javax.servlet.http.*;
public class Ch1Servlet extends HttpServlet{
 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  PrintWriter writer = resp.getWriter();
  Date today = new Date();
  writer.println("<html>"+
  "<body>" + "<h1 align=center>HF's Chapter Servlet</h1>"
    + "<br>" + today + "</body>" + "</html>");
 }
}

  • Line 7: Servlet將會extends HttpServlet
  • Line 9: Servlet會收到container建立的HttpServletRequest req, HttpServletResponse resp
  • Line 10: 可使用resp內的getWriter()取得將HTML寫到回應object上的PrintWriter




service()是由GenericServlet繼承來的

2017年12月2日 星期六

JSP-Servlet (3) - Servlet & Deployment Descriptor產生動態網頁

Web Server(如Apache)的
  • 可以做:
  1. client 請求網頁,找到該靜態網頁,不會做計算
  2. 原封不動地拿出此靜態網頁,添加header
  3. 傳送回client(每個client看到的東西都一樣)
  • 不能做:(但是可以找到能夠處理此request的application(如Tomcat))
  1. 產生動態網頁
  2. 將資料存在server
Servlet Java檔案
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.*;
import javax.servlet.http.*;
public class Ch1Servlet extends HttpServlet{
 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  PrintWriter writer = resp.getWriter();
  Date today = new Date();
  writer.println("<html>"+
  "<body>" + "<h1 align=center>HF's Chapter Servlet</h1>"
    + "<br>" + today + "</body>" + "</html>");
 }
}

Servlet Deployment Descriptor(web.xml)檔,部署描述檔
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://xmlns.jcp.org/xml/ns/javaee"
 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
 id="WebApp_ID" version="3.1">
 <servlet>
  <servlet-name>Ch1 Servlet</servlet-name>
  <servlet-class>Ch1Servlet</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>Ch1 Servlet</servlet-name>
  <url-pattern>/serv1</url-pattern>
 </servlet-mapping>
</web-app>
  • servlet-class: 真實,完整的servlet class名字,但不含.class (file path name)
  • servlet-name: alias (deploy name)
  • url-pattern: 使用者連線時請求的名稱(public URL name)
以上的命名目的為安全性及可維護性
執行結果:















Ref:
Eclipse 安裝tomcat:
Eclipse下使用tomcat的位置當作deploy位置

JSP-Servlet (2) - HTML & HTTP

HTML & HTTP差異:
  • HTML: (HyperText Markup Language 超文字標記語言) 瀏覽器必須了解的語言。瀏覽器是一種知道如何和伺服器溝通的軟體(如Safari, Mozilla)。當伺服器回應請求的時候,通常會傳給瀏覽器一組以HTML寫成的指令,由瀏覽器解譯HTML後將內容呈現給使用者。但有時候較舊版的瀏覽器可能會不了解使用新版HTML語法所寫的網頁內容
  • HTTP: (HyperText Transport Language 超文字傳輸協定) client及server之間的對話大多是HTTP(以此溝通),此協定支援簡單的request&response。基本上web說的語言就是HTTP。web server透過HTTP將HTML送給client。因此其實HTTP回應內包含HTML
又,HTTP執行在TCP/IP上。
- TCP負責將資料完整地從一個node傳送到另一個node。在運送過程有可能會被分割成幾個部分。但最後能保有完整性。
- IP是將封包從一台主機順利繞道一台主機的底層網路協定。
HTTP是支援web特定功能的網路協定。但依賴TCP/IP取得完整請求與回應

HTTP request關鍵元素:
  1. HTTP method
  2. URL
  3. Form parameters
HTTP response關鍵元素:
  1. Status Code
  2. Content-type
  3. Content
HTTP method:
  1. GET: 簡單的請求。如,要求server取出資源(HTML, JPEG file, PDF file等)。但也可以傳送(一點)資源

    • 傳送字元數量有限,取決於server(tomcat在conf/server.xml內可更改maxHttpHeaderSize="65536"參數),因此如果client在search bar輸入很長的資料,GET可能會無法運作
    • 安全性問題,GET會將資量附加在URL後面,出現在瀏覽器的URL欄位中。如帳號密碼等敏感資料
    • 如果使用POST代替GET,就不能把Form submission的頁面加入我的最愛當成書籤
    • 下例是一個GET的範例,使用?將路徑與參數隔開,參數間以&連結。兩個部分加起來得到的字串就是HTTP request所傳送的完整URL
    • http://ecshweb.pchome.com.tw/search/v3.3/?q=花茶%20&scope=all&sortParm=rnk&sortOrder=dc&cateId=DBAJ11

  2. POST: 像是Get的加強版,如了可以取出server資源,以能夠傳送使用者的資料
    • 設計為傳送複雜請求
    • 使用者在網頁上填的資料(如表單等),就會被加到message body (或稱為payload),資料量可以很大
  3. HEAD
  4. TRACE
  5. PUT
  6. DELETE
  7. OPTIONS
  8. CONNECT

MIME Type:
response header內的content type的值,就是MIME Type,他告知接收瀏覽器即將要接收怎麼樣的資料,好讓瀏覽器知道要怎麼展示


此值對應了request內header的Accept欄位(瀏覽器可以接受哪一種格式)

網頁傳送步驟:
  1. 使用者在search bar輸入URL
  2. 瀏覽器建立HTTP GET request
  3. 瀏覽器將此HTTP GET 請求傳送至server
  4. server根據某種對應關係找到該頁面
  5. server產生HTTP response
  6. 將其頁面傳回至client
  7. 瀏覽器收到後,根據HTTP內的HTML解譯,並將結果呈現給使用者
URL:(Uniform Resource Locator)
如下範例:
https://www.wangsteak.com.tw:443/advice/wang/menu.html
  • https: (告訴server這是哪一種protocal,此例為https)
  • www.wangsteak.com.tw: server, 實體server的獨特名字,對應到IP,可以直接使用IP代替server,但通常domain name比較好記
  • 443: port。server的很多應用程式會以port區隔。http預設是80
    • 一台server可以有0-65535,共65536個 (0~1023 port已經保留給一些知名的服務)
    • FTP: 21
    • Telnet: 23
    • POP3: 110
    • SMTP: 25
    • TIME server: 37
  • advice/wang: path,server被請求的網路位置
  • menu.html: resource,請求的檔案。假如被省略大部分會預設加上index.html

JSP-Servlet (1) - Mac下安裝Tomcat

註:須先確認安裝Java且設定完成環境變數$JAVA_HOME
  1. Tomcat官網下載,拉到最下面可以看到Binary Distributions,選擇合適的版本,若不確定則選擇Core發行的版本
  2. 解壓縮後會得到一個apache-tomcat-[version] 文件夾
  3. 將整包資料夾放入想要安裝tomcat的位置,且可將apache-tomcat-[version] 直接改為tomcat
  4. 這個安裝tomcat的位置,就是CATALINA_HOME
  5. 開啟Terminal,設定環境變數
  6. vim ~/.bash_profile
    
  7. 在檔案內新增一行 (~/Document/tomcat須代換為安裝tomcat的位置)
  8. export CATALINA_HOME=~/Document/tomcat
    
  9. 執行source重新讀取bash_profile
  10. source ~/.bash_profile
  11. 執行echo確認環境變數存在
  12. echo $CATALINA_HOME
  13. 啟動tomcat,至~/Document/tomcat/bin執行startup.sh(~/Document/tomcat須代換為安裝tomcat的位置)
  14. sh startup.sh
若安裝成功,至 http://localhost:8080/ 可看到Tomcat歡迎頁面。