当前位置: 首页 > news >正文

电脑如何做网站用xml可不可以做网站

电脑如何做网站,用xml可不可以做网站,学校做网站及费用,泰安注册公司在上一部分中#xff0c;我们为经理和员工实现了控制器。 既然我们知道了自己的出路#xff0c;我们将做很少#xff08;但仅做很少#xff09;更复杂的事情-任务和时间表的控制器。 因此#xff0c;让我们从org.timesheet.web开始。 TaskController 。 首先创建一个类我们为经理和员工实现了控制器。 既然我们知道了自己的出路我们将做很少但仅做很少更复杂的事情-任务和时间表的控制器。 因此让我们从org.timesheet.web开始。 TaskController 。 首先创建一个类这次我们将访问更丰富的域因此我们需要为任务员工和经理自动连接三个DAOS。 Controller RequestMapping(/tasks) public class TaskController {private TaskDao taskDao;private EmployeeDao employeeDao;private ManagerDao managerDao;Autowiredpublic void setTaskDao(TaskDao taskDao) {this.taskDao taskDao;}Autowiredpublic void setEmployeeDao(EmployeeDao employeeDao) {this.employeeDao employeeDao;}Autowiredpublic void setManagerDao(ManagerDao managerDao) {this.managerDao managerDao;}public EmployeeDao getEmployeeDao() {return employeeDao;}public TaskDao getTaskDao() {return taskDao;}public ManagerDao getManagerDao() {return managerDao;} } 让我们处理/ tasks上的GET请求 /*** Retrieves tasks, puts them in the model and returns corresponding view* param model Model to put tasks to* return tasks/list*/RequestMapping(method RequestMethod.GET)public String showTasks(Model model) {model.addAttribute(tasks, taskDao.list());return tasks/list;} 我们将把JSP放在任务子文件夹中。 首先是用于显示所有任务的list.jsp。 它不仅遍历所有任务而且在每个任务上遍历员工 % page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixfmt urihttp://java.sun.com/jsp/jstl/fmt % % taglib prefixspring urihttp://www.springframework.org/tags % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core% % taglib prefixsf urihttp://www.springframework.org/tags/form%!-- resolve variables -- %--elvariable idtasks typejava.util.Listorg.timesheet.domain.Task--%html headtitleTasks/titlelink relstylesheet href/timesheet-app/resources/style.css typetext/css /head bodyh1List of tasks/h1a hreftasks?newAdd new task/atable cellspacing5 classmain-table widetrth stylewidth: 35%;Description/ththManager/ththEmployees/ththCompleted/thth stylewidth: 20%;Details/ththDelete/th/trc:forEach items${tasks} vartasktrtd${task.description}/tdtda hrefmanagers/${task.manager.id}${task.manager.name}/a/tdtdc:forEach items${task.assignedEmployees} varempa hrefemployees/${emp.id}${emp.name}/a/c:forEach/tdtddiv classdeletec:choosec:when test${task.completed}Done/c:whenc:when test${!task.completed}In progress/c:when/c:choose/div/tdtda hreftasks/${task.id}Go to page/a/tdtdsf:form actiontasks/${task.id} methoddelete cssClassdeleteinput typesubmit value classdelete-button //sf:form/td/tr/c:forEach/tablebr /a hrefwelcomeGo back/a /body /html 照常删除任务 /*** Deletes task with specified ID* param id Tasks ID* return redirects to tasks if everything was ok* throws TaskDeleteException When task cannot be deleted*/RequestMapping(value /{id}, method RequestMethod.DELETE)public String deleteTask(PathVariable(id) long id) throws TaskDeleteException {Task toDelete taskDao.find(id);boolean wasDeleted taskDao.removeTask(toDelete);if (!wasDeleted) {throw new TaskDeleteException(toDelete);}// everything OK, see remaining tasksreturn redirect:/tasks;} TaskDeleteException package org.timesheet.web.exceptions;import org.timesheet.domain.Task;/*** When task cannot be deleted.*/ public class TaskDeleteException extends Exception {private Task task;public TaskDeleteException(Task task) {this.task task;}public Task getTask() {return task;} } 处理此异常的方法 /*** Handles TaskDeleteException* param e Thrown exception with task that couldnt be deleted* return binds task to model and returns tasks/delete-error*/ExceptionHandler(TaskDeleteException.class)public ModelAndView handleDeleteException(TaskDeleteException e) {ModelMap model new ModelMap();model.put(task, e.getTask());return new ModelAndView(tasks/delete-error, model);} JSP页面jsp / tasks / delete-error.jsp用于显示删除错误 %--elvariable idtask typeorg.timesheet.domain.Task--%html headtitleCannot delete task/title /head bodyOops! Resource a href${task.id}${task.description}/a can not be deleted.pMake sure there are no timesheets assigned on task./pbr /br /br /a href../welcomeBack to main page./a /body /html 显示任务的详细信息将通过URI / tasks / {id}访问。 我们将同时在模型中添加任务和可以添加到任务中的未分配员工。 它将像这样处理 /*** Returns task with specified ID* param id Taskss ID* param model Model to put task to* return tasks/view*/RequestMapping(value /{id}, method RequestMethod.GET)public String getTask(PathVariable(id) long id, Model model) {Task task taskDao.find(id);model.addAttribute(task, task);// add all remaining employeesListEmployee employees employeeDao.list();SetEmployee unassignedEmployees new HashSetEmployee();for (Employee employee : employees) {if (!task.getAssignedEmployees().contains(employee)) {unassignedEmployees.add(employee);}}model.addAttribute(unassigned, unassignedEmployees);return tasks/view;} 现在事情有些复杂了。 我们想显示任务的用户详细信息页面。 在此任务上我们要添加/删除分配给它的员工。 首先让我们考虑一下URL。 任务已分配了员工因此用于访问任务中员工的URL将如下所示 / tasks / {id} / employees / {employeeId} 要删除员工我们只需使用DELETE方法访问此资源因此让我们向控制器添加方法 /*** Removes assigned employee from task* param taskId Tasks ID* param employeeId Assigned employees ID*/RequestMapping(value /{id}/employees/{employeeId}, method RequestMethod.DELETE)ResponseStatus(HttpStatus.NO_CONTENT)public void removeEmployee(PathVariable(id) long taskId,PathVariable(employeeId) long employeeId) {Employee employee employeeDao.find(employeeId);Task task taskDao.find(taskId);task.removeEmployee(employee);taskDao.update(task);} 在视图页面上我们稍后会看到我们将简单地使用jQuery更改DOM模型并从列表中删除分配的员工。 让我们假装什么都不会出错我们有NO_CONTENT响应因此员工将总是成功地从数据库中删除。 因此我们可以简单地更改DOM模型。 对于添加员工我们将有未分配员工的选择列表或组合框。 删除员工后我们会将其添加到可用员工的选择中他再次可用。 添加员工后我们将使用DAO更改Task并将其重定向回同一任务所有内容都会更新。 这是将员工分配给任务的代码 /*** Assigns employee to tak* param taskId Tasks ID* param employeeId Employees ID (to assign)* return redirects back to altered task: tasks/taskId*/RequestMapping(value /{id}/employees/{employeeId}, method RequestMethod.PUT)public String addEmployee(PathVariable(id) long taskId,PathVariable(employeeId) long employeeId) {Employee employee employeeDao.find(employeeId);Task task taskDao.find(taskId);task.addEmployee(employee);taskDao.update(task);return redirect:/tasks/ taskId;} 最后使用task / view.jsp了解Task的详细信息。 正如我提到的那样有很多DOM更改因此此代码似乎比平时更难。 % page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixsf urihttp://www.springframework.org/tags/form% % taglib prefixc urihttp://java.sun.com/jsp/jstl/core%%--elvariable idtask typeorg.timesheet.domain.Task--% %--elvariable idunassigned typejava.util.Listorg.timesheet.domain.Employee--%html headtitleTask page/titlelink relstylesheet href/timesheet-app/resources/style.css typetext/css /head bodyh2Task info/h2div idlistullilabel fordescriptionDescription:/labelinput namedescription iddescription value${task.description}disabled${task.completed ? disabled : } //lililabel formanagerManager:/labelinput namemanager idmanager value${task.manager.name}disabledtrue //lililabel foremployeesEmployees:/labeltable idemployees classtask-tablec:forEach items${task.assignedEmployees} varemptrsf:form action${task.id}/employees/${emp.id} methoddeletetda href../employees/${emp.id} idhref-${emp.id}${emp.name}/a/tdtdinput typesubmit valueRemove idremove-${emp.id} /script src/timesheet-app/resources/jquery-1.7.1.js/scriptscript typetext/javascript$(#remove-${emp.id}).on(click, function() {$(#remove-${emp.id}).addClass(hidden);$(#href-${emp.id}).remove();// add to list of unassignedvar opt document.createElement(option);opt.setAttribute(value, ${emp.id});opt.textContent ${emp.name};$(#selected-emp).append(opt);});/script/td/sf:form/tr/c:forEach/table/lililabel forunassignedUnassgined:/labeltable idunassigned classtask-tabletrsf:form methodput idadd-formtdselect idselected-empc:forEach items${unassigned} varuempoption value${uemp.id}${uemp.name}/option/c:forEach/select/tdtdinput typesubmit valueAdd idadd-employee /script src/timesheet-app/resources/jquery-1.7.1.js/scriptscript typetext/javascript$(#add-employee).on(click, function() {$(#selected-emp).selected().remove();});/script/td/sf:form/tr/table/li/ul/divbr /br /a href../tasksGo Back/ascript src/timesheet-app/resources/jquery-1.7.1.js/scriptscript typetext/javascript(function() {// prepare default form actionsetAddAction();// handler for changing action$(#selected-emp).on(change, function() {setAddAction();});function setAddAction() {var id $(#selected-emp).val();$(#add-form).attr(action, ${task.id}/employees/ id);}})();/script /body /html 从代码中可以看到我们再次仅使用HTML JavaScript。 唯一特定于JSP的是将数据从模型带到页面。 OK现在我们必须能够创建新的Task。 让我们准备用于提供表单的控制器以添加将从/ tasksnew访问的任务 /*** Creates form for new task.* param model Model to bind to HTML form* return tasks/new*/RequestMapping(params new, method RequestMethod.GET)public String createTaskForm(Model model) {model.addAttribute(task, new Task());// list of managers to choose fromListManager managers managerDao.list();model.addAttribute(managers, managers);return tasks/new;} 任务包括名称经理和分配的员工。 在本教程的范围内我决定不实施最后一个。 我们只会产生一些员工。 如果您希望能够从某种选择列表中挑选员工并将他们分配给任务那么请注意这应该异步进行。 为此您可以将特殊方法映射到控制器并使用$ .post与jQuery进行AJAX发布。 我认为对于本教程来说这太少了但是如果您对如何在Spring中使用AJAX感兴趣请查看有关Spring 3中的ajax简化的博客文章 。 在创建员工和经理时我们仅将原始类型用于属性。 现在我们想为任务分配实际的Manager实例。 因此我们必须告诉Spring如何将选择列表经理的ID中的值转换为实际实例。 为此我们将使用自定义的PropertyEditorSupport工具。 添加新的org.timesheet.web.editors包创建新类ManagerEditor与下面的代码 public class ManagerEditor extends PropertyEditorSupport {private ManagerDao managerDao;public ManagerEditor(ManagerDao managerDao) {this.managerDao managerDao;}Overridepublic void setAsText(String text) throws IllegalArgumentException {long id Long.parseLong(text);Manager manager managerDao.find(id);setValue(manager);} } ManagerEditor将在其构造函数中传递DAO。 它将通过ID查找实际的管理员并调用父级的setValue。 Spring现在应该知道有这样一个编辑器因此我们必须在控制器中注册它。 我们只需要将WebDataBinder作为参数的方法并需要使用InitBinder注释对其进行注释如下所示 InitBinderprotected void initBinder(WebDataBinder binder) {binder.registerCustomEditor(Manager.class, new ManagerEditor(managerDao));} 就是这样Spring现在知道如何直接从表单将经理分配给我们的任务。 最后保存任务的代码。 如前所述在保存之前我们将招募一些员工来执行任务 /*** Saves new task to the database* param task Task to save* return redirects to tasks*/RequestMapping(method RequestMethod.POST)public String addTask(Task task) {// generate employeesListEmployee employees reduce(employeeDao.list());task.setAssignedEmployees(employees);taskDao.add(task);return redirect:/tasks;} 有reduce方法这是减少内存中员工的简单辅助方法。 这并不是十分有效我们可以使用更复杂的查询来做到这一点但现在就可以了。 如果需要也可以随意滚动自己的归约逻辑 /*** Reduces list of employees to some smaller amount.* Simulates user interaction.* param employees Employees to reduced* return New list of some employees from original employees list*/private ListEmployee reduce(ListEmployee employees) {ListEmployee reduced new ArrayListEmployee();Random random new Random();int amount random.nextInt(employees.size()) 1;// max. five employeesamount amount 5 ? 5 : amount;for (int i 0; i amount; i) {int randomIdx random.nextInt(employees.size());Employee employee employees.get(randomIdx);reduced.add(employee);employees.remove(employee);}return reduced;} 现在让我们看一下task / new.jsp页面 % page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixsf urihttp://www.springframework.org/tags/form% % taglib prefixc urihttp://java.sun.com/jsp/jstl/core%%--elvariable idtask typeorg.timesheet.domain.Task--% %--elvariable idmanagers typejava.util.Listorg.timesheet.domain.Manager--%html headtitleAdd new task/titlelink relstylesheet href/timesheet-app/resources/style.css typetext/css /head bodyh2Add new Task/h2div idlistsf:form methodpost actiontasks commandNametaskullilabel fordescriptionDescription:/labelinput namedescription iddescription value${task.description} //lililabel formanager-selectManager:/labelsf:select pathmanager idmanager-selectsf:options items${managers} itemLabelname itemValueid //sf:select/liliEmployees will be generated .../liliinput typesubmit valueSave/li/ul/sf:form/divbr /br /a hreftasksGo Back/a/body /html 当然要测试控制器 package org.timesheet.web;import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.Model; import org.springframework.web.servlet.ModelAndView; import org.timesheet.DomainAwareBase; import org.timesheet.domain.Employee; import org.timesheet.domain.Manager; import org.timesheet.domain.Task; import org.timesheet.service.dao.EmployeeDao; import org.timesheet.service.dao.ManagerDao; import org.timesheet.service.dao.TaskDao; import org.timesheet.web.exceptions.TaskDeleteException;import java.util.Collection; import java.util.List;import static org.junit.Assert.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when;ContextConfiguration(locations {/persistence-beans.xml, /controllers.xml}) public class TaskControllerTest extends DomainAwareBase {private Model model; // used for controllerAutowiredprivate TaskDao taskDao;Autowiredprivate ManagerDao managerDao;Autowiredprivate EmployeeDao employeeDao;Autowiredprivate TaskController controller;Beforepublic void setUp() {model new ExtendedModelMap(); }Afterpublic void cleanUp() {ListTask tasks taskDao.list();for (Task task : tasks) {taskDao.remove(task);}}Testpublic void testShowTasks() {// prepare some dataTask task sampleTask();// use controllerString view controller.showTasks(model);assertEquals(tasks/list, view);ListTask listFromDao taskDao.list();Collection? listFromModel (Collection?) model.asMap ().get(tasks);assertTrue(listFromModel.contains(task));assertTrue(listFromDao.containsAll(listFromModel));}Testpublic void testDeleteTaskOk() throws TaskDeleteException {Task task sampleTask();long id task.getId();// delete assertString view controller.deleteTask(id);assertEquals(redirect:/tasks, view);assertNull(taskDao.find(id));}Test(expected TaskDeleteException.class)public void testDeleteTaskThrowsException() throws TaskDeleteException {Task task sampleTask();long id task.getId();// mock DAO for this callTaskDao mockedDao mock(TaskDao.class);when(mockedDao.removeTask(task)).thenReturn(false);TaskDao originalDao controller.getTaskDao();try {// delete expect exceptioncontroller.setTaskDao(mockedDao);controller.deleteTask(id);} finally {controller.setTaskDao(originalDao);}}Testpublic void testHandleDeleteException() {Task task sampleTask();TaskDeleteException e new TaskDeleteException(task);ModelAndView modelAndView controller.handleDeleteException(e);assertEquals(tasks/delete-error, modelAndView.getViewName());assertTrue(modelAndView.getModelMap().containsValue(task));}Testpublic void testGetTask() {Task task sampleTask();long id task.getId();// get assertString view controller.getTask(id, model);assertEquals(tasks/view, view);assertEquals(task, model.asMap().get(task));}Testpublic void testRemoveEmployee() {Task task sampleTask();long id task.getAssignedEmployees().get(0).getId();controller.removeEmployee(task.getId(), id);// task was updated inside controller in other transaction - refreshtask taskDao.find(task.getId());// get employee assertEmployee employee employeeDao.find(id);assertFalse(task.getAssignedEmployees().contains(employee));}Testpublic void testAddEmployee() {Task task sampleTask();Employee cassidy new Employee(Butch Cassidy, Cowboys);employeeDao.add(cassidy);controller.addEmployee(task.getId(), cassidy.getId());// task was updated inside controller in other transaction - refreshtask taskDao.find(task.getId());// get employee assertEmployee employee employeeDao.find(cassidy.getId());assertTrue(task.getAssignedEmployees().contains(employee));}Testpublic void testAddTask() {Task task sampleTask();// save via controllerString view controller.addTask(task);assertEquals(redirect:/tasks, view);// task is in DBassertEquals(task, taskDao.find(task.getId()));}private Task sampleTask() {Manager manager new Manager(Jesse James);managerDao.add(manager);Employee terrence new Employee(Terrence, Cowboys);Employee kid new Employee(Sundance Kid, Cowboys);employeeDao.add(terrence);employeeDao.add(kid);Task task new Task(Wild West, manager, terrence, kid);taskDao.add(task);return task;} } 任务就是这样。 现在让我们为时间表创建控制器。 为我们需要的控制器和自动接线的DAO添加基本样板 Controller RequestMapping(/timesheets) public class TimesheetController {private TimesheetDao timesheetDao;private TaskDao taskDao;private EmployeeDao employeeDao;Autowiredpublic void setTimesheetDao(TimesheetDao timesheetDao) {this.timesheetDao timesheetDao;}Autowiredpublic void setTaskDao(TaskDao taskDao) {this.taskDao taskDao;}Autowiredpublic void setEmployeeDao(EmployeeDao employeeDao) {this.employeeDao employeeDao;}public TimesheetDao getTimesheetDao() {return timesheetDao;}public TaskDao getTaskDao() {return taskDao;}public EmployeeDao getEmployeeDao() {return employeeDao;} } 在时间表上处理GET请求的方法 /*** Retrieves timesheets, puts them in the model and returns corresponding view* param model Model to put timesheets to* return timesheets/list*/RequestMapping(method RequestMethod.GET)public String showTimesheets(Model model) {ListTimesheet timesheets timesheetDao.list();model.addAttribute(timesheets, timesheets);return timesheets/list;} JSP将放置在时间表子文件夹中。 添加list.jsp页面该页面基本上将遍历Timesheet的属性并滚动删除表单 % page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixfmt urihttp://java.sun.com/jsp/jstl/fmt % % taglib prefixspring urihttp://www.springframework.org/tags % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core% % taglib prefixsf urihttp://www.springframework.org/tags/form%!-- resolve variables -- %--elvariable idtimesheets typejava.util.Listorg.timesheet.domain.Timesheet--%html headtitleTimesheets/titlelink relstylesheet href/timesheet-app/resources/style.css typetext/css /head bodyh1List of timesheets/h1a hreftimesheets?newAdd new timesheet/atable cellspacing5 classmain-table widetrth stylewidth: 30%Employee/thth stylewidth: 50%Task/ththHours/ththDetails/ththDelete/th/trc:forEach items${timesheets} vartstrtda hrefemployees/${ts.who.id}${ts.who.name}/a/tdtda hreftasks/${ts.task.id}${ts.task.description}/a/tdtd${ts.hours}/tdtda hreftimesheets/${ts.id}Go to page/a/tdtdsf:form actiontimesheets/${ts.id} methoddelete cssClassdeleteinput typesubmit classdelete-button/sf:form/td/tr/c:forEach/tablebr /a hrefwelcomeGo back/a /body /html 删除时间表比删除任务更容易因为我们不会破坏数据库中的任何约束因此我们可以在DAO上使用默认的remove方法 /*** Deletes timeshet with specified ID* param id Timesheets ID* return redirects to timesheets*/RequestMapping(value /{id}, method RequestMethod.DELETE)public String deleteTimesheet(PathVariable(id) long id) {Timesheet toDelete timesheetDao.find(id);timesheetDao.remove(toDelete);return redirect:/timesheets;} 我们将照常通过将其ID添加到URI来访问单个时间表资源因此我们将处理/ timesheets / {id}。 但是有分配给时间表的对象-任务实例和员工实例。 我们不希望表单将其无效。 因此我们将为表单引入轻量级的命令支持对象。 我们将只更新小时然后在实际的时间表实例中设置这些新小时 /*** Returns timesheet with specified ID* param id Timesheets ID* param model Model to put timesheet to* return timesheets/view*/RequestMapping(value /{id}, method RequestMethod.GET)public String getTimesheet(PathVariable(id) long id, Model model) {Timesheet timesheet timesheetDao.find(id);TimesheetCommand tsCommand new TimesheetCommand(timesheet);model.addAttribute(tsCommand, tsCommand);return timesheets/view;} 这是TimesheetCommand的代码现在位于新包org.timesheet.web下。 命令 package org.timesheet.web.commands;import org.hibernate.validator.constraints.Range; import org.timesheet.domain.Timesheet;import javax.validation.constraints.NotNull;public class TimesheetCommand {NotNullRange(min 1, message Hours must be 1 or greater)private Integer hours;private Timesheet timesheet;// default c-tor for bean instantiationpublic TimesheetCommand() {}public TimesheetCommand(Timesheet timesheet) {hours timesheet.getHours();this.timesheet timesheet;}public Integer getHours() {return hours;}public void setHours(Integer hours) {this.hours hours;}public Timesheet getTimesheet() {return timesheet;}public void setTimesheet(Timesheet timesheet) {this.timesheet timesheet;}Overridepublic boolean equals(Object o) {if (this o) {return true;}if (o null || getClass() ! o.getClass()) {return false;}TimesheetCommand that (TimesheetCommand) o;if (hours ! null ? !hours.equals(that.hours) : that.hours ! null) {return false;}if (timesheet ! null ? !timesheet.equals(that.timesheet) : that.timesheet ! null) {return false;}return true;}Overridepublic int hashCode() {int result hours ! null ? hours.hashCode() : 0;result 31 * result (timesheet ! null ? timesheet.hashCode() : 0);return result;} } 很简单但是NotNull和Range注释是什么 好吧我们绝对不希望用户输入小时数为负数或零因此我们将使用此简洁的JSR 303 Bean验证API。 要使其工作只需将对Hibernate验证器的依赖项添加到pom.xml中 dependencygroupIdorg.hibernate/groupIdartifactIdhibernate-validator/artifactIdversion4.2.0.Final/version/dependency 将Hibernate Validator放入我们的类路径后将自动选择默认的验证器。 为了使其工作我们必须启用注释驱动的MVC因此将以下行添加到timesheet-servlet.xml bean配置文件中 mvc:annotation-driven / 我们将在几行后看到有效模型的用法。 现在在时间表文件夹下我们将创建view.jsp页面其中包含有关单个时间表的信息 % page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixsf urihttp://www.springframework.org/tags/form% % taglib prefixc urihttp://java.sun.com/jsp/jstl/core%%--elvariable idtsCommand typeorg.timesheet.web.commands.TimesheetCommand--%html headtitleTimesheet page/titlelink relstylesheet href/timesheet-app/resources/style.css typetext/css /head bodyh2Timesheet info/h2div idlistsf:form methodpost modelAttributetsCommandsf:errors path* cssClasserrors elementdiv /ullilabel foremployeeNameAssigned employee:/labela idemployee href../employees/${tsCommand.timesheet.who.id}${tsCommand.timesheet.who.name}/a/lililabel fortaskTask:/labela idtask href../tasks/${tsCommand.timesheet.task.id}${tsCommand.timesheet.task.description}/a/lililabel forhoursHours:/labelinput namehours idhours value${tsCommand.hours} //liliinput typesubmit valueSave //li/ul/sf:form/divbr /br /a href../timesheetsGo Back/a /body /html 在此视图页面中我们具有提交按钮该按钮将触发/ timesheets / {id}上的POST请求并传递更新的模型该模型中的TimesheetCommand实例。 因此让我们处理一下。 我们将使用Valid批注它是JSR 303 Bean验证API的一部分用于标记要验证的对象。 另请注意必须使用ModelAttribute批注对TimesheetCommand进行批注因为此命令已绑定到Web视图。 验证错误存储在BindingResult对象中 /*** Updates timesheet with given ID* param id ID of timesheet to lookup from DB* param tsCommand Lightweight command object with changed hours* return redirects to timesheets*/RequestMapping(value /{id}, method RequestMethod.POST)public String updateTimesheet(PathVariable(id) long id,Valid ModelAttribute(tsCommand) TimesheetCommand tsCommand,BindingResult result) {Timesheet timesheet timesheetDao.find(id);if (result.hasErrors()) {tsCommand.setTimesheet(timesheet);return timesheets/view;}// no errors, update timesheettimesheet.setHours(tsCommand.getHours());timesheetDao.update(timesheet);return redirect:/timesheets;} 要进行添加我们必须从现有任务和员工的选择菜单中进行选择因此在提供新表单时我们将传递这些列表 /*** Creates form for new timesheet* param model Model to bind to HTML form* return timesheets/new*/RequestMapping(params new, method RequestMethod.GET)public String createTimesheetForm(Model model) {model.addAttribute(timesheet, new Timesheet());model.addAttribute(tasks, taskDao.list());model.addAttribute(employees, employeeDao.list());return timesheets/new;} 为了显示员工和任务的选择列表我们再次需要为其创建编辑器。 我们之前已经看到了这种方法因此像以前一样我们向我们的项目中添加2个使用相应DAO的新编辑器 package org.timesheet.web.editors;import org.timesheet.domain.Employee; import org.timesheet.service.dao.EmployeeDao;import java.beans.PropertyEditorSupport;/*** Will convert ID from combobox to employees instance.*/ public class EmployeeEditor extends PropertyEditorSupport {private EmployeeDao employeeDao;public EmployeeEditor(EmployeeDao employeeDao) {this.employeeDao employeeDao;}Overridepublic void setAsText(String text) throws IllegalArgumentException {long id Long.parseLong(text);Employee employee employeeDao.find(id);setValue(employee);} }package org.timesheet.web.editors;import org.timesheet.domain.Task; import org.timesheet.service.dao.TaskDao;import java.beans.PropertyEditorSupport;public class TaskEditor extends PropertyEditorSupport {private TaskDao taskDao;public TaskEditor(TaskDao taskDao) {this.taskDao taskDao;}Overridepublic void setAsText(String text) throws IllegalArgumentException {long id Long.parseLong(text);Task task taskDao.find(id);setValue(task);} } 我们将在TimesheetController initBinder方法中注册这些编辑器 InitBinderprotected void initBinder(WebDataBinder binder) {binder.registerCustomEditor(Employee.class, new EmployeeEditor(employeeDao));binder.registerCustomEditor(Task.class, new TaskEditor(taskDao));} 现在我们可以安全地在timesheets文件夹下添加new.jsp 因为选择列表将正确地填充有模型中传递的数据 % taglib prefixsf urihttp://www.springframework.org/tags/form % % page contentTypetext/html;charsetUTF-8 languagejava %%--elvariable idemployees typejava.util.Listorg.timesheet.domain.Employee--% %--elvariable idtasks typejava.util.Listorg.timesheet.domain.Task--%html headtitleAdd new timesheet/titlelink relstylesheet href/timesheet-app/resources/style.css typetext/css /head bodyh2Add new Timesheet/h2div idlistsf:form methodpost actiontimesheets commandNametimesheetullilabel foremployeesPick employee:/labelsf:select pathwho idemployeessf:options items${employees} itemLabelname itemValueid //sf:select/lililabel fortasksPick task:/labelsf:select pathtask idtaskssf:options items${tasks} itemLabeldescription itemValueid //sf:select/lililabel forhoursHours:/labelsf:input pathhours //liliinput typesubmit valueSave //li/ul/sf:form/divbr /br /a hreftimesheetsGo Back/a /body /html Submit按钮在/ timesheets路径上提交POST请求因此我们将使用非常简单的控制器方法来处理此请求 /*** Saves new Timesheet to the database* param timesheet Timesheet to save* return redirects to timesheets*/RequestMapping(method RequestMethod.POST)public String addTimesheet(Timesheet timesheet) {timesheetDao.add(timesheet);return redirect:/timesheets;} 因此所有时间表功能现在都应该可以正常工作只需确保使用应用程序一段时间即可。 当然我们现在还将为TimesheetController编写单元测试。 在测试方法testUpdateTimesheetValid和testUpdateTimesheetInValid中我们不是手动验证对象而是模拟验证器 package org.timesheet.web;import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.timesheet.DomainAwareBase; import org.timesheet.domain.Employee; import org.timesheet.domain.Manager; import org.timesheet.domain.Task; import org.timesheet.domain.Timesheet; import org.timesheet.service.dao.EmployeeDao; import org.timesheet.service.dao.ManagerDao; import org.timesheet.service.dao.TaskDao; import org.timesheet.service.dao.TimesheetDao; import org.timesheet.web.commands.TimesheetCommand;import java.util.Collection; import java.util.List;import static org.junit.Assert.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when;ContextConfiguration(locations {/persistence-beans.xml, /controllers.xml}) public class TimesheetControllerTest extends DomainAwareBase {Autowiredprivate TimesheetDao timesheetDao;Autowiredprivate EmployeeDao employeeDao;Autowiredprivate ManagerDao managerDao;Autowiredprivate TaskDao taskDao;Autowiredprivate TimesheetController controller;private Model model; // used for controllerBeforepublic void setUp() {model new ExtendedModelMap();}Testpublic void testShowTimesheets() {// prepare some dataTimesheet timesheet sampleTimesheet();// use controllerString view controller.showTimesheets(model);assertEquals(timesheets/list, view);ListTimesheet listFromDao timesheetDao.list();Collection? listFromModel (Collection?) model.asMap().get(timesheets);assertTrue(listFromModel.contains(timesheet));assertTrue(listFromDao.containsAll(listFromModel));}Testpublic void testDeleteTimesheet() {// prepare ID to deleteTimesheet timesheet sampleTimesheet();timesheetDao.add(timesheet);long id timesheet.getId();// delete assertString view controller.deleteTimesheet(id);assertEquals(redirect:/timesheets, view);assertNull(timesheetDao.find(id));}Testpublic void testGetTimesheet() {// prepare timesheetTimesheet timesheet sampleTimesheet();timesheetDao.add(timesheet);long id timesheet.getId();TimesheetCommand tsCommand new TimesheetCommand(timesheet);// get assertString view controller.getTimesheet(id, model);assertEquals(timesheets/view, view);assertEquals(tsCommand, model.asMap().get(tsCommand));}Testpublic void testUpdateTimesheetValid() {// prepare ID to deleteTimesheet timesheet sampleTimesheet();timesheetDao.add(timesheet);long id timesheet.getId();TimesheetCommand tsCommand new TimesheetCommand(timesheet);// user alters Timesheet hours in HTML form with valid valuetsCommand.setHours(1337);BindingResult result mock(BindingResult.class);when(result.hasErrors()).thenReturn(false);// update assertString view controller.updateTimesheet(id, tsCommand, result);assertEquals(redirect:/timesheets, view);assertTrue(1337 timesheetDao.find(id).getHours());}Testpublic void testUpdateTimesheetInValid() {// prepare ID to deleteTimesheet timesheet sampleTimesheet();timesheetDao.add(timesheet);long id timesheet.getId();TimesheetCommand tsCommand new TimesheetCommand(timesheet);Integer originalHours tsCommand.getHours();// user alters Timesheet hours in HTML form with valid valuetsCommand.setHours(-1);BindingResult result mock(BindingResult.class);when(result.hasErrors()).thenReturn(true);// update assertString view controller.updateTimesheet(id, tsCommand, result);assertEquals(timesheets/view, view);assertEquals(originalHours, timesheetDao.find(id).getHours());}Testpublic void testAddTimesheet() {// prepare timesheetTimesheet timesheet sampleTimesheet();// save but via controllerString view controller.addTimesheet(timesheet);assertEquals(redirect:/timesheets, view);// timesheet is stored in DBassertEquals(timesheet, timesheetDao.find(timesheet.getId()));}private Timesheet sampleTimesheet() {Employee marty new Employee(Martin Brodeur, NHL);employeeDao.add(marty);Manager jeremy new Manager(Jeremy);managerDao.add(jeremy);Task winStanleyCup new Task(NHL finals, jeremy, marty);taskDao.add(winStanleyCup);Timesheet stanelyCupSheet new Timesheet(marty, winStanleyCup, 100);timesheetDao.add(stanelyCupSheet);return stanelyCupSheet;} } 我们要做的最后一个控制器是针对我们的特殊业务服务– TimesheetService。 我们已经实现并测试了它的逻辑。 Controller会将这些功能简单地合并到一个菜单页面我们将使用Controller处理每个功能。 因此让我们首先添加一些样板控制器定义和DAO布线 Controller RequestMapping(/timesheet-service) public class TimesheetServiceController {private TimesheetService service;private EmployeeDao employeeDao;private ManagerDao managerDao;Autowiredpublic void setService(TimesheetService service) {this.service service;}Autowiredpublic void setEmployeeDao(EmployeeDao employeeDao) {this.employeeDao employeeDao;}Autowiredpublic void setManagerDao(ManagerDao managerDao) {this.managerDao managerDao;}} 当用户使用GET请求进入/ timesheet-service时我们将使用填充的数据为他提供菜单服务 /*** Shows menu of timesheet service: * that contains busiest task and employees and managers to* look for their assigned tasks.* param model Model to put data to* return timesheet-service/list*/RequestMapping(method RequestMethod.GET)public String showMenu(Model model) {model.addAttribute(busiestTask, service.busiestTask());model.addAttribute(employees, employeeDao.list());model.addAttribute(managers, managerDao.list());return timesheet-service/menu;} 再次为了使内容在选择列表中起作用我们将注册编辑器我们将仅重用最近创建的编辑器 InitBinderprotected void initBinder(WebDataBinder binder) {binder.registerCustomEditor(Employee.class, new EmployeeEditor(employeeDao));binder.registerCustomEditor(Manager.class, new ManagerEditor(managerDao));} 现在我们将提供服务。 我们将再次拥有RESTful URL但是实际资源不会像以前那样直接映射到域模型而是一些内部服务的结果。 因此获取ID为123的经理的任务将导致GET请求时间表/ manager-tasks / 123。 员工任务相同。 我们将使用选择列表的侦听器与jQuery形成实际的URL。 添加时间表服务文件夹并在其中添加menu.jsp页面其内容如下 % taglib prefixsf urihttp://www.springframework.org/tags/form % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % % page contentTypetext/html;charsetUTF-8 languagejava %%--elvariable idbusiestTask typeorg.timesheet.domain.Task--% %--elvariable idmanagers typejava.util.Listorg.timesheet.domain.Manager--% %--elvariable idemployees typejava.util.Listorg.timesheet.domain.Employee--%html headtitleTimesheet Service/titlelink relstylesheet href/timesheet-app/resources/style.css typetext/css /head bodyh1Timesheet services/h1div idlisth3Busiest task/h3ullia href/timesheet-app/tasks/${busiestTask.id}idbusiest-task${busiestTask.description}/a/li/ulh3Tasks for manager/h3sf:form methodget idmanager-formulliselect idselect-managersc:forEach items${managers} varmanoption value${man.id}${man.name}/option/c:forEach/select/liliinput typesubmit valueSearch //li/ul/sf:formh3Tasks for employee/h3sf:form methodget idemployee-formulliselect idselect-employeesc:forEach items${employees} varempoption value${emp.id}${emp.name}/option/c:forEach/select/liliinput typesubmit valueSearch/li/ul/sf:form/divbr /br /a href/timesheet-app/welcomeGo Back/ascript src/timesheet-app/resources/jquery-1.7.1.js/scriptscript typetext/javascript(function() {// set default actionssetAddAction(#select-managers, #manager-form, manager-tasks);setAddAction(#select-employees, #employee-form, employee-tasks);// handler for chaning action$(#select-managers).on(change, function() {setAddAction(#select-managers, #manager-form, manager-tasks);});$(#select-employees).on(change, function() {setAddAction(#select-employees, #employee-form, employee-tasks);});function setAddAction(selectName, formName, action) {var id $(selectName).val();$(formName).attr(action,/timesheet-app/timesheet-service/ action / id);}})();/script /body /html 获取给定经理的任务 /*** Returns tasks for given manager* param id ID of manager* param model Model to put tasks and manager* return timesheet-service/manager-tasks*/RequestMapping(value /manager-tasks/{id}, method RequestMethod.GET)public String showManagerTasks(PathVariable(id) long id, Model model) {Manager manager managerDao.find(id);ListTask tasks service.tasksForManager(manager);model.addAttribute(manager, manager);model.addAttribute(tasks, tasks);return timesheet-service/manager-tasks;} 结果页面timesheet -service / manager-tasks.jsp将呈现 % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % % page contentTypetext/html;charsetUTF-8 languagejava %%--elvariable idmanager typeorg.timesheet.domain.Manager--% %--elvariable idtasks typejava.util.Listorg.timesheet.domain.Task--%html headtitleTasks for manager/titlelink relstylesheet href/timesheet-app/resources/style.css typetext/css /head bodyh3Current manager: a href/timesheet-app/managers/${manager.id}${manager.name}/a/h3div idlistc:forEach items${tasks} vartasklia href/timesheet-app/tasks/${task.id}${task.description}/a/li/c:forEach/divbr /br /a href../Go Back/a /body /html 我们将为员工做几乎相同的事情 /*** Returns tasks for given employee* param id ID of employee* param model Model to put tasks and employee* return timesheet-service/employee-tasks*/RequestMapping(value /employee-tasks/{id}, method RequestMethod.GET)public String showEmployeeTasks(PathVariable(id) long id, Model model) {Employee employee employeeDao.find(id);ListTask tasks service.tasksForEmployee(employee);model.addAttribute(employee, employee);model.addAttribute(tasks, tasks);return timesheet-service/employee-tasks;} 然后用jsp查看employee-tasks.jsp % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % % page contentTypetext/html;charsetUTF-8 languagejava %%--elvariable idemployee typeorg.timesheet.domain.Employee--% %--elvariable idtasks typejava.util.Listorg.timesheet.domain.Task--%html headtitleTasks for employee/titlelink relstylesheet href/timesheet-app/resources/style.css typetext/css /head bodyh3Current employee: a href/timesheet-app/employees/${employee.id}${employee.name}/a/h3div idlistc:forEach items${tasks} vartasklia href/timesheet-app/tasks/${task.id}${task.description}/a/li/c:forEach/divbr /br /a href../Go Back/a /body /html 因此请确保一切都集成良好并为此新contoller添加单元测试 package org.timesheet.web;import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.FileSystemResource; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.jdbc.SimpleJdbcTestUtils; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.Model; import org.timesheet.DomainAwareBase; import org.timesheet.domain.Employee; import org.timesheet.domain.Manager; import org.timesheet.service.TimesheetService; import org.timesheet.service.dao.EmployeeDao; import org.timesheet.service.dao.ManagerDao;import static org.junit.Assert.assertEquals;/*** This test relies on fact that DAOs and Services are tested individually.* Only compares, if controller returns the same as individual services.*/ ContextConfiguration(locations {/persistence-beans.xml, /controllers.xml}) public class TimesheetServiceControllerTest extends DomainAwareBase {Autowiredprivate TimesheetServiceController controller;Autowiredprivate TimesheetService timesheetService;Autowiredprivate EmployeeDao employeeDao;Autowiredprivate ManagerDao managerDao;Autowiredprivate SimpleJdbcTemplate jdbcTemplate;private Model model;private final String createScript src/main/resources/sql/create-data.sql;Beforepublic void setUp() {model new ExtendedModelMap();SimpleJdbcTestUtils.executeSqlScript(jdbcTemplate,new FileSystemResource(createScript), false);}Testpublic void testShowMenu() {String view controller.showMenu(model);assertEquals(timesheet-service/menu, view);assertEquals(timesheetService.busiestTask(),model.asMap().get(busiestTask));// this should be done only on small data sample// might cause serious performance cost for completeassertEquals(employeeDao.list(), model.asMap().get(employees));assertEquals(managerDao.list(), model.asMap().get(managers));}Testpublic void testShowManagerTasks() {// prepare some IDManager manager managerDao.list().get(0);long id manager.getId();String view controller.showManagerTasks(id, model);assertEquals(timesheet-service/manager-tasks, view);assertEquals(manager, model.asMap().get(manager));assertEquals(timesheetService.tasksForManager(manager),model.asMap().get(tasks));}Testpublic void testShowEmployeeTasks() {// prepare some IDEmployee employee employeeDao.list().get(0);long id employee.getId();String view controller.showEmployeeTasks(id, model);assertEquals(timesheet-service/employee-tasks, view);assertEquals(employee, model.asMap().get(employee));assertEquals(timesheetService.tasksForEmployee(employee),model.asMap().get(tasks));} } 这部分之后的项目结构所有新内容都可见 最终请求映射 参考 第5部分–在vrtoonjava博客上从我们的JCG合作伙伴 Michal Vrtiak 添加Spring MVC第2部分 。 翻译自: https://www.javacodegeeks.com/2012/09/spring-adding-spring-mvc-part-2.html
http://www.pierceye.com/news/697786/

相关文章:

  • 企业形象网站开发名师工作室网站建设
  • o2o网站建设最好公司排名做竹鼠网站
  • 免费做网站软件2003商丘网络营销服务
  • 杭州网站建设加q479185700如何网上外贸接单
  • 针对茅台酒企业网站建设方案鸿基建设工程有限公司网站
  • 有创意营销型网站建设wordpress 慢集市
  • 注册网站多少钱永康电子商务网站建设
  • 江西省网站建设庆阳在线网
  • wordpress建站微信联系智慧政务网站怎么做
  • 邯郸购物网站建设电子商务是干什么的工作
  • 网站开发竞聘报告wordpress彩色标签云设置方法
  • 深圳高端网站建设收费宿州百度seo排名软件
  • 彩妆网站建设报告公司网页是什么
  • 站长之家综合查询工具广州网站网站建设
  • 网站开发如何实现数据库的链接同性性做视频网站
  • 网站建设uuiop网站建设盐城最便宜
  • iss怎么做网站一个旅游网站建设
  • 润州网站建设网址生成
  • 备案网站服务内容域名网站打开慢
  • 做网站域名备案需要多久企业年金查询官网
  • 制作企业网站的公司如何制作广告
  • 兰州网站优化excel做网站链接
  • 代做单片机毕业设计网站广州网站建设小程序开发
  • 深圳网站官网建设方案安阳做网站电话
  • 批量扫dedecms做的网站哪个网站可以兼职做效果图
  • 建网站与建网页的区别wordpress 七牛云 cdn
  • 专门做养老院的网站城市文化网站开发背景
  • html5写的网站有什么好处淄博网站制作制作
  • 服装设计素材网站大全做旅游的网站的要素
  • 企业网站建设报价清单深圳小程序建设公司