- 任務由經理分配給員工。 一項任務可以分配給許多員工。
- 員工將他在某些任務上工作的小時數填滿至系統。
- 經理/員工查看時間表上的報告(時間表可以更改)。
讓我們稍微回顧一下這些要點,然后嘗試將這種簡單的人類語言轉換為程序員可以發現的某些關系和實體。
- 實體:經理,員工,時間表,任務
好的,我們現在應該對領域有了更好的了解,所以讓我們創建maven項目并實現類。 使用Maven,您將獲得漂亮而干凈的項目結構。 您所需要做的就是安裝Maven,并在項目中包含pom.xml。 您可以“手動”執行此操作,并通過終端構建應用程序(在這種情況下,只需創建常規項目并添加pom.xml文件)。 我更喜歡使用一些其他工具。 IntelliJ IDEA,NetBeans和Springsource Tool Suite具有現成的Maven支持。 如果您使用的是純Eclipse,請檢查m2eclipse插件。
無論哪種方式,這都是我們項目的一些基本Maven配置:
<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd'><modelVersion>4.0.0</modelVersion><groupId>org.timesheet</groupId><artifactId>org.timesheet</artifactId><version>0.0.1-SNAPSHOT</version><name>Timesheet Management On Spring</name><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.6</source><target>1.6</target></configuration></plugin></plugins></build>
</project>
現在讓我們實現領域模型。 創建包org.timesheet.domain并定義以下類。
package org.timesheet.domain;public class Employee {private String name;private String department;public Employee(String name, String department) {this.name = name;this.department = department;}public String getName() {return name;}public String getDepartment() {return department;}
}
package org.timesheet.domain;public class Manager {private String name;public Manager(String name) {this.name = name;}public String getName() {return name;}
}
package org.timesheet.domain;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class Task {private List<Employee> assignedEmployees = new ArrayList<Employee>();private Manager manager;private boolean completed;private String description;public Task(String description, Manager manager, Employee... employees) {this.description = description;this.manager = manager;assignedEmployees.addAll(Arrays.asList(employees));completed = false;}public Manager getManager() {return manager;}public List<Employee> getAssignedEmployees() {return assignedEmployees;}public void addEmployee(Employee e) {assignedEmployees.add(e);}public void removeEmployee(Employee e) {assignedEmployees.remove(e);}public void completeTask() {completed = true;}
}
package org.timesheet.domain;public class Timesheet {private Employee who;private Task task;private Integer hours;public Timesheet(Employee who, Task task, Integer hours) {this.who = who;this.task = task;this.hours = hours;}public Employee getWho() {return who;}public Task getTask() {return task;}public Integer getHours() {return hours;}/*** Manager can alter hours before closing task* @param hours New amount of hours*/public void alterHours(Integer hours) {this.hours = hours;}@Overridepublic String toString() {return 'Timesheet [who=' + who + ', task=' + task + ', hours=' + hours+ ']';}}
如您所見,Manager和Employee類沒有很多屬性,它們在這里只是為了擁有類型安全模型。 在“現實世界”中,他們可能還有其他各種屬性,例如姓,生日,地址等等,甚至可能是普通的父類。
而且,我們現在并不真正在乎各種約束。 例如,我們只能在任務上填寫整數小時,依此類推。
現在是時候定義我們的服務層–定義業務操作并為這些操作建立接口。 因此,讓我們制作軟件包org.timesheet.service 。 首先,我們將創建GenericDao接口,在其中我們將為系統中的每個實體定義基本的CRUD操作。
package org.timesheet.service;import java.util.List;public interface GenericDao<E, K> {void add(E entity);void update(E entity);void remove(E entity);E find(K key);List<E> list();}
現在,讓我們不必擔心實際的持久層-讓我們創建一些虛擬實現并將所有數據存儲在內存中。 我們將其放入新包– org.timesheet.service.impl中 。 不用擔心,稍后我們將使用Hibernate。 這是虛擬實現的代碼:
package org.timesheet.service.impl;import java.util.ArrayList;
import java.util.List;import org.timesheet.service.GenericDao;public class InMemoryDao<E, K> implements GenericDao<E, K> {private List<E> entities = new ArrayList<E>();@Overridepublic void add(E entity) {entities.add(entity);}@Overridepublic void update(E entity) {throw new UnsupportedOperationException('Not supported in dummy in-memory impl!');}@Overridepublic void remove(E entity) {entities.remove(entity);}@Overridepublic E find(K key) {if (entities.isEmpty()) {return null;}// just return the first one sice we are not using any keys ATMreturn entities.get(0);}@Overridepublic List<E> list() {return entities;}}
接下來,我們將編寫我們的第一個簡單測試。 現在,我們將第一個依賴項添加到pom.xml文件的JUnit庫中。 因為它是第一個,所以我們還需要將其包裝到dependencies元素中,如下所示:
<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.10</version></dependency></dependencies>
這是我們針對Employee DAO的第一個非常簡單的單元測試。 我們現在不做其他任何事情,因為我們還沒有真正要測試的東西。 但是,更重要的是,我們如何依賴測試中DAO的實現(我們使用新的InMemoryDao… )。 這很不好,因為我們應該只測試定義接口的公共API。 在本教程的后面,您將看到Spring如何幫助我們解決此類問題。
package org.timesheet.service;import static org.junit.Assert.*;import java.util.List;import org.junit.Before;
import org.junit.Test;
import org.timesheet.domain.Employee;
import org.timesheet.service.impl.InMemoryDao;public class EmployeeDaoTest {private GenericDao<Employee, Long> employeeDao = new InMemoryDao<Employee, Long>();@Beforepublic void setUp() {for (int i = 0; i < 5; i++) {Employee e = new Employee('Mike ' + i, 'IT');employeeDao.add(e);}}@Testpublic void testAdd() {int oldSize = employeeDao.list().size();Employee e = new Employee('Bob', 'IT');employeeDao.add(e);int newSize = employeeDao.list().size();assertFalse (oldSize == newSize);}@Testpublic void testRemove() {int oldSize = employeeDao.list().size();Employee e = employeeDao.find(1L);employeeDao.remove(e);int newSize = employeeDao.list().size();assertFalse (oldSize == newSize);}@Testpublic void testUpdate() {//TODO: need real implementation}@Testpublic void testList() {List<Employee> list = employeeDao.list();assertNotNull (list);assertFalse (list.isEmpty());}}
如果需要,還可以為其他DAO的其余測試編寫單元測試。 但是由于我們現在沒有合適的實現來測試,因此我們稍后將一起進行測試。
事情并非總是那么容易。 這不僅與CRUD操作有關,還與業務操作不夠通用,無法用簡單的DAO表示出來。 因此,讓我們定義一些業務操作并為其創建單獨的服務。 我們將其稱為TimesheetService。
package org.timesheet.service;import org.timesheet.domain.Employee;
import org.timesheet.domain.Manager;
import org.timesheet.domain.Task;import java.util.List;/*** Business that defines operations on timesheets*/
public interface TimesheetService {/*** @return Finds the busiest task (with the most of employees).* Returns {@code null} when tasks are empty.*/Task busiestTask();/*** Finds all the tasks for the employee.* @param e Employee* @return Tasks*/List<Task> tasksForEmployee(Employee e);/*** Finds all the tasks for the manager.* @param m Manager* @return Tasks*/List<Task> tasksForManager(Manager m);}
好的,到目前為止很好。 您現在已經知道在下一個示例中我們將使用什么業務領域。 您可能現在想知道-我們還沒有使用Spring,為什么呢? 請記住, Spring的最初目的是簡化企業Java開發并鼓勵POJO開發模型。 因此,將Spring與該基本模型一起使用將非常容易,因此我們不會將核心邏輯與不必要的依賴項混合在一起。
在下面的圖片中,到目前為止,我們已經構建了項目的結構,因此請確保您表現良好。

參考: 第1部分–在vrtoonjava博客上,由我們的JCG合作伙伴 Michal Vrtiak 設計域模型和服務層 。
翻譯自: https://www.javacodegeeks.com/2012/09/spring-designing-domain-model-and.html