@Action public class ProductAction { @Request("GET:/product") public Page index() { ...... } @Request("POST:/product/create") public Result create(Map<String, Object> fieldMap, List<Multipart> multipartList) { ...... } @Request("PUT:/product/update/{id}") public Result update(long id, Map<String, Object> fieldMap) { ...... } @Request("DELETE:/product/delete/{id}") public Result delete(long id) { ...... } }
public Page index(); public Result delete(long id) public Page search(Map<String, Object> fieldMap) public Result update(long id, Map<String, Object> fieldMap) public Result create(List<Multipart> multipartList) public Result create(Map<String, Object> fieldMap, List<Multipart> multipartList) public Result uploadPicture(long id, Map<String, Object> fieldMap, List<Multipart> multipartList) ......
Action方法返回值容許爲void、Page、Result三種。 java
a. 以void爲返回值的方法,處理完業務後,不作後續操做,例以下載等。 mysql
b. 以Page爲返回值的方法,則轉發或重定向到相應的頁面中。 ajax
Page經常使用方法: sql
void setPath(String path);//設置路徑 void setData(Map<String, Object> data);//設置參數
c. 以Result爲返回值的方法,則返回包含基本信息的json字符串。 數據庫
Result經常使用方法: json
void setSuccess(boolean success);//設置成功標誌 void setError(int error);//設置錯誤代碼 void setData(Object data);//設置響應數據
借鑑 Spring IOC 的思路,可將任意的類標註爲@Bean,當應用啓動時,框架會自動建立這些 Bean實例,並放入容器中。隨後可以使用 BeanHelper.getBean() 方法獲取對應的 Bean實例。通常狀況下,會將 Action類標註爲@Action,Service實現類標註爲 @Service,可在 Action類中使用 @Inject註解注入所需的 Service接口。 app
Action類: @Action public class ProductAction { @Inject private ProductService productService; ... } Service 實現類: @Service public class ProductServiceImpl implements ProductService { ... }若在項目中一個接口同時存在多個實現類,此時只能選擇其中的一個實現類生效,可在接口上使用 @Impl指定具體的實現類。
方法 框架 |
說明 jsp |
void begin() ide |
在進入方法時執行。 |
boolean intercept(Method method, Object[] args) |
設置過濾條件。默認返回 true,表示無過濾條件。 |
void before(Method method, Object[] args) |
在目標方法調用前執行。 |
void after(Method method, Object[] args) |
在目標方法調用後執行。 |
void error(Method method, Object[] args, Exception e) |
在拋出異常時執行。 |
void end() |
在方法執行完畢前執行。 |
如下編寫了一個 Aspect 類,用於橫切 com.smart.sample.action下全部類的方法,除了SystemAction類,代碼以下:
@Aspect(pkg = "com.smart.sample.action") @Order(0) public class AccessAspect extends AspectProxy { @Override public boolean intercept(Class<?> cls, Method method, Object[] params) throws Exception { boolean result = true; if (cls == SystemAction.class) { result = false; } return result; } @Override public void before(Class<?> cls, Method method, Object[] params) throws Exception { Long userId = DataContext.Session.get(Constant.USER_ID); if (userId == null) { WebUtil.setRedirectURL(DataContext.getRequest(), Constant.REDIRECT_URL); throw new AccessException(); } } }可在 intercept() 方法中,對目標方法(Method 對象)的名稱、參數、返回值、註解等信息設置過濾條件。
public class Product extends BaseEntity { private long productTypeId; private String productName; private String productCode; private int price; private String description; ... getter/setter 方法 }
映射規則以下:
Entity 類 |
數據庫 |
類名(如:Product) |
表名(如:product) |
屬性名(如:productTypeId) |
列名(如:product_type_id) |
可見,將 Entity 類的類名與屬性名的「駝峯式」轉爲「下劃線式」,即爲數據庫的表名與列名。若表名帶有前綴(如:t_product),則此時須要藉助 @Table 註解,將其標註在 Entity 類上,在該註解的參數中指定所對應的表名(如:@Table(「t_product」))。
同理,對於屬性名與列名的不規則映射規則,能夠藉助 @Column 註解實現映射關係。當列名爲 Java 關鍵字時(如:class),須要考慮此方案。
在本框架中使用「貧血式」模型,不使用 OneToMany、ManyToOne、ManyToMany 等「充血式」模型,也就是說,一個 Entity 與一個 Table 對應,一個 Property 與一個 Column 對應。建議使用 Java 原始類型,而不是封裝類型,如:建議使用 int,而不是 Integer。
Entity 屬性類型只能從如下類型中選擇:
類型 |
說明 |
int |
對於長度較小的數值類型數據,推薦使用 int 類型,不要使用 Integer 類型。 |
long |
對於長度較長的數值類型數據,推薦使用 long 類型,不要使用 Long 類型。 |
double |
對於全部的浮點類型數據,推薦使用 double 類型,不要使用 Double、float/Float 等類型。 |
String |
對於字符類型數據,推薦使用 String 類型,不要使用 char 類型。 |
注意:對於日期或時間,推薦使用 String 或 long 類型,而不要使用 Date 類型。
@Action public class ProductAction { @Inject private ProductService productService; ... @Request("get:/product/{id}") public Result getProductById(long productId) { if (productId == 0) { return new Result(false).error(ERROR_PARAM); } Product product = productService.getProduct(productId); if (product != null) { return new Result(true).data(product); } else { return new Result(false).error(ERROR_DATA); } } ... }當 productId 爲 0 時,返回一個 Result 對象,成功標誌爲 false,錯誤代碼 ERROR_PARAM(值爲 10)。錯誤代碼可統必定義。
... $.ajax({ url: '/product/' + productId, type: 'get', success: function(result) { if (result.success) { var product = result.data; $('#product_type_id').val(product.productTypeId); $('#product_name').val(product.productName); $('#product_code').val(product.productCode); $('#price').val(product.price); $('#description').val(product.description); } else { switch (result.error) { case 10: alert('The parameter is error!'); break; case 20: alert('The data is error!'); break; } } } }); ...
public class ProductServiceTest extends BaseTest { private ProductService productService = BeanHelper.getBean(ProductServiceImpl.class); @BeforeClass @AfterClass public static void init() { initSQL("sql/product.sql"); } @Test @Order(1) public void getProductListTest() { List<Product> productList = productService.getProductList(); Assert.assertNotNull(productList); Assert.assertEquals(productList.size(), 7); } @Test @Order(2) public void getProductTest() { long productId = 1; Product product = productService.getProduct(productId); Assert.assertNotNull(product); } ... }Test 類必須繼承 BaseTest 類。在類中可以使用 BeanHelper.getBean() 方法初始化相關的 Bean 實例(這裏是 Service 實現類實例),注意:此時不能使用 @Inject 實現依賴注入。可以使用 JUnit 提供的 @Test、@BeforeClass、@AfterClass 等註解來標註被測方法。在 init() 方法上同時標註了 @BeforeClass 與 @AfterClass,表示該方法會在測試以前與測試以後被 JUnit 框架所調用,用於執行數據初始化腳本,該腳本在 test/resources/sql/ 目錄下。
#應用名稱 app.name=smart-sample #Action類所在的包 app.package=com.smart.sample #網站靜態資源路徑 app.www_path=/www/ #jsp路徑 app.jsp_path=/WEB-INF/jsp/ #登陸地址 app.home_page=/login #上傳文件尺寸大小(MB) app.upload_limit=10 #數據庫類型 jdbc.type=mysql #驅動名 jdbc.driver=com.mysql.jdbc.Driver #數據庫連接地址 jdbc.url=jdbc:mysql://localhost:3306/sample #登陸名 jdbc.username=root #密碼 jdbc.password=root #是否動態加載i18n文件 i18n.reloadable=true #上傳路徑 sample.upload_path=/www/upload/