代码结构

域对象 spittle.java

package _5BuildingSpringwebapplications.domain;import java.util.Date;import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;public class Spittle {private final Long id;private final String message;private final Date time;private Double latitude;private Double longitude;public Spittle(String message, Date time) {this(message, time, null, null);}public Spittle(String message, Date time, Double longitude, Double latitude) {this.id = null;this.message = message;this.time = time;this.longitude = longitude;this.latitude = latitude;}public long getId() {return id;}public String getMessage() {return message;}public Date getTime() {return time;}public Double getLongitude() {return longitude;}public Double getLatitude() {return latitude;}@Overridepublic boolean equals(Object that) {return EqualsBuilder.reflectionEquals(this, that, "id", "time");}@Overridepublic int hashCode() {return HashCodeBuilder.reflectionHashCode(this, "id", "time");}}

dao层SpittleRepositoryImpl.java,示例中没有没有内容,但是在源码中有实际内容,即相关的sql查询,但是本章还没有涉及到系统的后端,这样的话,只能通过mockito校验controller层,不能在浏览器中操作连接.

package _5BuildingSpringwebapplications.repository;import java.util.List;
import org.springframework.stereotype.Repository;import _5BuildingSpringwebapplications.domain.Spittle;@Repository
public class SpittleRepositoryImpl implements SpittleRepository{@Overridepublic List<Spittle> findSpittles(long max, int count) {return null;}@Overridepublic Spittle findOne(long spittleId) {// TODO Auto-generated method stubreturn null;}}

controller层,SpittleController.java,这里没有明确的区别controller层和service层

package _5BuildingSpringwebapplications.web;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;import _5BuildingSpringwebapplications.domain.Spittle;
import _5BuildingSpringwebapplications.repository.SpittleRepository;@Controller
@RequestMapping({ "/spittles" })
public class SpittleController {private static final String MAX_LONG_AS_STRING = "9223372036854775807";private SpittleRepository spittleRepository;@Autowiredpublic SpittleController(SpittleRepository spittleRepository) {// TODO Auto-generated constructor stubthis.spittleRepository = spittleRepository;}//  @RequestMapping(method = RequestMethod.GET)
//  public String spittles(Model model) {
//      model.addAttribute("spittleList",spittleRepository.findSpittles(Long.MAX_VALUE, 20));/* 默认的属性名是spittleList */
//      return "spittles";/*这个默认的View名就是spittles*/
//  }@RequestMapping(method = RequestMethod.GET)public List<Spittle> spittles(@RequestParam(value = "max",defaultValue = MAX_LONG_AS_STRING) long max,@RequestParam(value = "count", defaultValue = "20") int count) {return spittleRepository.findSpittles(max, count);}@RequestMapping(value = "/show", method = RequestMethod.GET)public String showSpittle(@RequestParam("spittle_id") long spittleId, Model model) {model.addAttribute(spittleRepository.findOne(spittleId));return "spittle";}//explicit about the model key// @RequestMapping(method = RequestMethod.GET)// public String spittles(Model model) {// model.addAttribute("spittleList",// spittleRepository.findSpittles(Long.MAX_VALUE, 20));// return "spittles";// }//work with a non-Spring type
//  @RequestMapping(method = RequestMethod.GET)
//  public String spittles(Map model) {
//      model.put("spittleList", spittleRepository.findSpittles(Long.MAX_VALUE, 20));
//      return "spittles";
//  } //total different from the others,the model key is inferred from its type (spittleList, as in the other examples
//  @RequestMapping(method=RequestMethod.GET)
//  public List<Spittle> spittles() {
//  return spittleRepository.findSpittles(Long.MAX_VALUE, 20));
//  }@RequestMapping(value = "/{spittleId}", method = RequestMethod.GET)public String spittle(@PathVariable("spittleId") long spittleId, Model model) {model.addAttribute(spittleRepository.findOne(spittleId));return "spittle";}}

对contrller层的校验,主要校验了是否能够返回正确的view名等.源码中mockito的相关方法只写了名字,eclipse不能自动识别,因为方法都是静态的,如果加上类名,即能正确识别.mokito很方便,实际上在用junit运行下面的代码时,不要求service层对应的方法有实际的内容.

package _5BuildingSpringwebapplications.web.test;import static org.hamcrest.Matchers.hasItems;import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.servlet.view.InternalResourceView;import _5BuildingSpringwebapplications.domain.Spittle;
import _5BuildingSpringwebapplications.repository.SpittleRepository;
import _5BuildingSpringwebapplications.web.SpittleController;public class SpittleControllerTest {@Testpublic void shouldShowRecentSpittles() throws Exception {List<Spittle> expectedSpittles = createSpittleList(20);SpittleRepository mockRepository = Mockito.mock(SpittleRepository.class);Mockito.when(mockRepository.findSpittles(Long.MAX_VALUE, 20)).thenReturn(expectedSpittles);SpittleController controller = new SpittleController(mockRepository);MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).setSingleView(new InternalResourceView("/WEB-INF/views/spittles.jsp")).build();mockMvc.perform(MockMvcRequestBuilders.get("/spittles")).andExpect(MockMvcResultMatchers.view().name("spittles")).andExpect(MockMvcResultMatchers.model().attributeExists("spittleList")).andExpect(MockMvcResultMatchers.model().attribute("spittleList", hasItems(expectedSpittles.toArray())));}private List<Spittle> createSpittleList(int count) {List<Spittle> spittles = new ArrayList<Spittle>();for (int i = 0; i < count; i++) {spittles.add(new Spittle("Spittle " + i, new Date()));}return spittles;}@Testpublic void shouldShowPagedSpittles() throws Exception {List<Spittle> expectedSpittles = createSpittleList(50);SpittleRepository mockRepository = Mockito.mock(SpittleRepository.class);Mockito.when(mockRepository.findSpittles(238900, 50)).thenReturn(expectedSpittles);SpittleController controller = new SpittleController(mockRepository);MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).setSingleView(new InternalResourceView("/WEB-INF/views/spittles.jsp")).build();mockMvc.perform(MockMvcRequestBuilders.get("/spittles?max=238900&count=50")).andExpect(MockMvcResultMatchers.view().name("spittles")).andExpect(MockMvcResultMatchers.model().attributeExists("spittleList")).andExpect(MockMvcResultMatchers.model().attribute("spittleList", Matchers.hasItems(expectedSpittles.toArray())));}@Testpublic void testSpittle() throws Exception {Spittle expectedSpittle = new Spittle("hello", new Date());SpittleRepository mockRepository = Mockito.mock(SpittleRepository.class);Mockito.when(mockRepository.findOne(12345)).thenReturn(expectedSpittle);SpittleController controller = new SpittleController(mockRepository);MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build();mockMvc.perform(MockMvcRequestBuilders.get("/spittles/12345")).andExpect(MockMvcResultMatchers.view().name("spittle")).andExpect(MockMvcResultMatchers.model().attributeExists("spittle")).andExpect(MockMvcResultMatchers.model().attribute("spittle", expectedSpittle));}}

junit运行结果

本示例没有贴出SpittleRepository.java即SpittleRepositoryImpl实现的接口.其实很简单,自己实现即可.

域对象spitter.java

package _5BuildingSpringwebapplications.domain;import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.validator.constraints.Email;public class Spitter {private Long id;@NotNull@Size(min = 5, max = 16)private String username;@NotNull@Size(min = 5, max = 25)private String password;@NotNull@Size(min = 2, max = 30)private String firstName;@NotNull@Size(min = 2, max = 30)private String lastName;@NotNull@Emailprivate String email;public Spitter() {}public Spitter(String username, String password, String firstName, String lastName, String email) {this(null, username, password, firstName, lastName, email);}public Spitter(Long id, String username, String password, String firstName, String lastName, String email) {this.id = id;this.username = username;this.password = password;this.firstName = firstName;this.lastName = lastName;this.email = email;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}@Overridepublic boolean equals(Object that) {return EqualsBuilder.reflectionEquals(this, that, "firstName", "lastName", "username", "password", "email");}@Overridepublic int hashCode() {return HashCodeBuilder.reflectionHashCode(this, "firstName", "lastName", "username", "password", "email");}
}

spitter对象的service层SpitterRepositoryImpl.java,与spittle的dao层一样,这里的方法都没有具体的内容,即没有与数据库的交互,这不影响对本章的理解.

package _5BuildingSpringwebapplications.repository;import org.springframework.stereotype.Repository;import _5BuildingSpringwebapplications.domain.Spitter;@Repository
public class SpitterRepositoryImpl implements SpitterRepository{@Overridepublic void save(Spitter spitter) {// TODO Auto-generated method stub}@Overridepublic Spitter findByUsername(String username) {// TODO Auto-generated method stubreturn null;}}

spitter的controller层SpitterController.java

package _5BuildingSpringwebapplications.web;import javax.validation.Valid;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;import _5BuildingSpringwebapplications.domain.Spitter;
import _5BuildingSpringwebapplications.repository.SpitterRepository;@Controller
@RequestMapping("/spitter")
public class SpitterController {private SpitterRepository spitterRepository;public SpitterController() {// TODO Auto-generated constructor stub}@Autowiredpublic SpitterController(SpitterRepository spitterRepository) {this.spitterRepository = spitterRepository;}@RequestMapping(value = "/register", method = RequestMethod.GET)public String showRegistrationForm() {return "registerForm";}@RequestMapping(value = "/register", method = RequestMethod.POST)public String proce***egistration(@Valid Spitter spitter, Errors errors) {if (errors.hasErrors()) {return "registerForm";}spitterRepository.save(spitter);return "redirect:/spitter/" + spitter.getUsername();}@RequestMapping(value = "/{username}", method = RequestMethod.GET)public String showSpitterProfile(@PathVariable String username, Model model) {Spitter spitter = spitterRepository.findByUsername(username);model.addAttribute(spitter);return "profile";}
}

代码中没有提到model层和view层.controller直接调的dao,本章的源码中也没有model层.可能因为涉及到的请求都比较简单,不需要太复杂的逻辑运行,直接由dao层返回,由view显示即可.

本章的内容除了介绍springmvc的一些知识点外,如何对controller进行单元测试也是一大亮点.

转载于:https://blog.51cto.com/tenfee/1872289

spring in action 4 第5章相关推荐

  1. 《Spring in Action》第4章-Spring Security

    Spring Security 开始使用Spring Security 加入依赖 <dependency><groupId>org.springframework.boot&l ...

  2. 第二章 装配Bean(Spring in action,3th)

                                         第二章 装配Bean 创建应用对象之间协作关系的行为通常被称为装配(wiring),是依赖注入的本质. XML方式声明Bean ...

  3. Spring in Action 4 读书笔记之使用标签创建 AOP

    目录 1. 定义一个 aspect 2. 创建一个 around advice 在之前的读书笔记 Spring in Acton 4 读书笔记之 AOP 原理及 Spring 对 AOP 的支持 中, ...

  4. Spring in Action 4th 学习笔记 之 AOP

    前提:本文中的AOP仅限于Spring AOP. 先说说为什么需要AOP 最简单的一个例子就是日志记录,如果想记录一些方法的执行情况,最笨的办法就是修改每一个需要记录的方法.但这,真的很笨... 好的 ...

  5. Spring in Action:@Vaild 表单验证不起作用

    在按照<Spring in Action>进行实践的过程中,发现@Vaild表单验证不起作用.最后查明原因如下: 仔细阅读<Spring in Action>,书中说: 从Sp ...

  6. Spring In Action 4

    在线学习连接:spring in action 4 文章目录 关键词解释 一.Spring的核心 1.1 简化Java开发 1.1.1 激发POJO的潜能 1.1.2 依赖注入 1.1.3 应用切面 ...

  7. 《小马哥讲Spring核心编程思想》-第一章学习笔记(1)

    <小马哥讲Spring核心编程思想>-第一章学习笔记(1) 一.课程介绍 1.为什么要学习spring? 2.深入学习spring的难点有哪些? 3.课程的设计思路是怎样的? 二.内容综述 ...

  8. Spring实战第五版第二章字段校验返回视图报错解决及javax.validation完整pom依赖

    Spring实战第五版第二章 2.3 校验表单输入 在编写"/design"页面post处理逻辑时,按照书本上直接'return "design"; '方式,会 ...

  9. Spring入门到精通:第一章 基础入门:1.Spring框架概述

    Spring入门到精通:第一章 基础入门:1.Spring框架概述 前言:为什么要学习Spring框架? 为什么要学习Spring框架呐? (1)使用广泛:现在很多的企业都有Spring的影子,不管是 ...

最新文章

  1. python官网下载步骤linux-linux下安装python
  2. shell排序_Java后端技术精选:希尔排序
  3. mysql切换到使用openssl,MySQL主从复制+OpenSSL
  4. 11 JVM 垃圾回收(上)
  5. 51单片机温度控制系统报警器,不会做课程设计的就拿走
  6. 计算机辅助设计和工程图学,工程制图与计算机辅助设计
  7. ae渲染出现错误是什么问题_怎样彻底检查根治AE导出失败,渲染影片出错问题...
  8. 拼图游戏 java_Java拼图游戏源码
  9. 自动控制理论——拉普拉斯变换定义及性质
  10. angular使用高德地图
  11. 基于WADE框架开发流程
  12. win10打开计算机闪屏,Win10打开资源管理器闪屏怎么办?Win10资源管理器闪屏问题的解决方法...
  13. 【云和恩墨大讲堂】SQL 审核 | 细致入微,方显价值
  14. 三次样条拟合(附完整代码)
  15. 永久一键关闭QQ频道,不用重新安装
  16. PHP中一些通用和易混淆技术点的最佳编程实践
  17. 最终,还是没能成为吹牛逼的资本!(二)
  18. ADI Blackfin DSP处理器-BF533的开发详解7:SPI接口的驱动和应用(含源代码)
  19. ssm+mysql+养老院信息管理系统 毕业设计-附源码181550
  20. 持续集成交付的流水作业

热门文章

  1. APUE学习笔记——第十章信号中10.15节例程的运行结果与书本里的不一样
  2. 比买电脑还便宜的桌面虚拟化方案
  3. 六类布线六大注意事项
  4. Spark学习之简介
  5. 面试题:找出出现次数超过1/2和1/3的数
  6. C之 #pragma(二十二)
  7. 我的AngularJS学习轨迹
  8. linux----------CentOS的一些除了yum安装以外的基本操作命令。
  9. 一个射击运动员打靶,靶一共有10环,连开10枪打中90环的可能性有多少种?请用递归算法编程实现。...
  10. Flex Timer 定时器