29 11月 2010

碎碎唸

個人覺得,工作可以是一種信仰、一種宗教,而一間公司可能同時存在有多種信仰;

信仰間是會有衝突的,有些信仰無法容下其他的信仰而有衝突,發生衝突時也難免會因較為激進的派系而交火;在人數極多時,我想這無可避免。

但如果一間人數極少而每個人竟都有不同的信仰,這個組合應該是一件蠢事。

這蠢事居然就在我眼前。

蠢!


10 11月 2010

Spring MVC (2) -- Tiles

Tiles是一個分割網頁的Library,提供了一個除了使用<jsp:include>之外的JSP組合工具;
透過xml設定檔,將重覆不需變動的頁面分割後定為Template,讓開發人員專注在各個模組中不同的頁面並使其具有組合性。

通常一個頁面基本的格局大概如下圖





這次的Demo就以table來分割而不以div方式來制定,簡單的html如下

<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title></title>
</head>
<body>
<table>
 <tr>
  <td colspan="2">Header</td>
 </tr>
 <tr>
  <td>Menu</td><td>Body</td>
 </tr>
 <tr>
  <td colspan="2">Footer</td>
 </tr>
</table>
</body>
</html> 

寫成JSP的include大概會變成下面這樣

<%@ page language="java" pageEncoding="UTF-8"%>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title></title>
</head>
<body>
<table>
 <tr>
  <td colspan="2"><jsp:include file="/WEB-INF/jsp/common/header.jsp"></jsp:include></td>
 </tr>
 <tr>
  <td><jsp:include file="/WEB-INF/jsp/common/menu.jsp"></jsp:include></td><td>Body</td>
 </tr>
 <tr>
  <td colspan="2"><jsp:include file="/WEB-INF/jsp/common/footer.jsp"></jsp:include></td>
 </tr>
</table>
</body>
</html> 

看起來還不錯,但是個一個jsp都必需重覆include header,menu,footer這三個jsp,而且萬一哪天出了什麼事,例如要加個ad在畫面的最右側,那所有的jsp都必需要被修正.....嗯,如果以部份認為PG死不完,班是應該的管理人員來看,也許也不是什麼大事吧....

但是Tiles提供了一個反其道而行的方式,先要求我們產生一個基本的jsp做為layout,將header,menu,body,footer當成是變數,再利用xml設定每個變數是要指到哪一個jsp,就讓我們一步一步看下去(。。。有點藍色xx網的感覺

(1)Library
先在pom.xml中加入要使用的library,如果僅是使用基本的tiles功能,只要加入一項即可
<dependency>

<dependency>
    <groupid>org.apache.tiles</groupid>
    <artifactid>tiles-jsp</artifactid>
    <version>2.2.2</version>
</dependency> 

(2)建立Template Layout JSP -- layout.jsp
簡單來說,就是利用tiles:insertAttribute來取代jsp:include
加入ignore="true"代表可以不給值。

<%@ include file="/WEB-INF/jsp/common/base.jsp"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title><tiles:insertattribute ignore="true" name="title"></tiles:insertattribute></title>
</head>
<body>
<table>
 <tr>
  <td colspan="2"><tiles:insertattribute name="header"> </tiles:insertattribute></td>
 </tr>
 <tr>
  <td><tiles:insertattribute name="menu"></tiles:insertattribute></td><td><tiles:insertattribute name="body"></tiles:insertattribute></td>
 </tr>
 <tr>
  <td colspan="2"><tiles:insertattribute name="footer"></tiles:insertattribute></td>
 </tr>
</table>
</body>
</html> 

(3)設定Tiles的Template XML -- tiles.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN" "http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
    <!--採用/WEB-INF/jsp/common/layout.jsp做為基本版型,-->
 <definition name="base.definition" template="/WEB-INF/jsp/common/layout.jsp">
  <put-attribute name="title" value="">
  </put-attribute><put-attribute name="header" value="/WEB-INF/jsp/common/header.jsp">
  </put-attribute><put-attribute name="menu" value="/WEB-INF/jsp/common/menu.jsp">
  </put-attribute><put-attribute name="body" value="">
  </put-attribute><put-attribute name="footer" value="/WEB-INF/jsp/common/footer.jsp">
 </put-attribute></definition>
    <!-- 延用基本版型,改變title與body的值 -->
 <definition name="hello" extends="base.definition">
  <put-attribute name="title" value="Say Hello to Tiles">
  </put-attribute><put-attribute name="body" value="/WEB-INF/jsp/helloTiles.jsp">
 </put-attribute></definition>
</tiles-definitions> 

而其中/WEB-INF/jsp/common/下的header.jsp,menu.jsp,footer.jsp,helloTiles.jsp就隨你寫入內容囉

(4)更改SpringMVC 的ViewReslover -- spring-servlet.xml
將先前採用的JstlView改為TilesView,並加入tilesConfigurer指定tiles設定檔

<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" id="viewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView">
 </property></bean>

 <bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer" id="tilesConfigurer">
  <property name="definitions">
   <list>
    <value>/WEB-INF/tiles.xml</value>
   </list>
  </property>
 </bean> 

這樣就完成最簡單的SpringMVC與Tiles設定囉


09 11月 2010

Spring MVC (1)

因為專案需要,但是專案沒有wiki的系統(說來Redmine真的不錯用!),就稍為利用這裡記錄關於SpringMVC想說明的部份

(1)library
要開始一個SpringMVC很容易,第一請先建立一個web project,要利用mvn eclipse:eclipse或直接在ide裡開都ok,pom.xml裡的dependency只需要

 <dependencies>
  <dependency>
   <groupid>org.springframework</groupid>
   <artifactid>spring-webmvc</artifactid>
   <version>3.0.5.RELEASE</version>
  </dependency>
  <dependency>
   <groupid>javax.servlet</groupid>
   <artifactid>jstl</artifactid>
   <version>1.2</version>
  </dependency>
 </dependencies> 

(2)web.xml
web.xml也很容易,只要將SpringMVC要用的front controller -- DispatcherServlet喚起就可以,而serlvet-mapping就看你高興,不喜歡以.do結尾也可用asp,php或html來混淆他人...下列的設定代表所有http://host/module/XXXX.do的url皆會由Spring的DispatcherServlet處理

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee">
 <servlet>
  <servlet-name>spring</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>spring</servlet-name>
  <url-pattern>*.do</url-pattern>
 </servlet-mapping>
</web-app> 


(3)spring-servlet.xml
如果你有沒有在web.xml利用ContextLoaderListener來載入的spring configuration,SpringMVC則會自動載入/WEB-INF/spring-servlet.xml,如果沒用ContextLoaderListener也找不到該檔就會顯示錯誤

<?xml version="1.0" encoding="UTF-8"?>
<beans xsi:schemalocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-3.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns="http://www.springframework.org/schema/beans">

 <context:component-scan base-package="idv.elliot.web.controller"/>

 <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" id="viewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView">
  </property><property name="prefix" value="/WEB-INF/jsp/">
  </property><property name="suffix" value=".jsp">
 </property></bean>
</beans> 

簡單來說,利用component-scan來找出利用annotation標示的Spring components,當中也包含了皆下來要提的Controller,然後建立一個viewResolver,這是用最基本的UrlBasedViewResolver
如此一來,當Controller的method回傳abc時,SpringMVC就會將其導向http://host/module/WEB-INF/jsp/abc.jsp
至於為什麼要把jsp放到/WEB-INF/下,則是因為這只要/WEB-INF/裡的所有東西必需是自系統內的servlet forward過去才能取得,一般人無法直接以url接觸到該resource

(4)建立Controller
先用個helloworld吧,Struts用Action,SpringMVC則是用Controller,
而要把Class當SpringMVC的Controller只要在Class前加上@Controller的annotation即可
基本的method則是return ModelAndView,然後在method前加上@RequestMapping的Annotation
下列這個Class說明當使用者輸入http://host/module/sayHello.do時即會呼叫HelloController.sayHello(),而回傳ModelAndView("hello")則是讓SpringMVC的ViewReslover找到對應的jsp。

package idv.elliot.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HelloController {
 
 @RequestMapping("/sayHello")
 public ModelAndView sayHello() {
  return new ModelAndView("hello");
 }
}

(5)hello.jsp
重點是jsp存放的位置,而不是jsp,請記得之前viewResolver的設定,要放在/WEB-INF/jsp/下即可

只要輸入http://host/module/sayHello.do就可以看到結果,而所有專案資料的截圖如下