第5章 构建Spring Web 应用程序 --笔记1

来源:互联网 发布:宁波知豆电动汽车公司 编辑:程序博客网 时间:2024/06/01 20:42

概述:

Spring的Web框架就是为了帮你解决这些关注点而设计的。SpringMVC基于模型-视图-控制器(Model-View-Controller,MVC)模式实现,它能够帮你构建像Spring框架那样灵活和松耦合的Web应用程序。


5.1 搭建SpringMVC

配置DispatcherServlet

这个不是基于web,而是通过java类来配置

package com.jack.config;import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;/** * 在Servlet3.0环境中,容器会在类路径中查询实现 * javax.servlet.ServletContainerInitializer 接口的类,如果发现的话,就会用它来配置Servlet容器 * @author Administrator * */public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class<?>[]{RootConfig.class};}@Overrideprotected Class<?>[] getServletConfigClasses() {return  new Class<?>[]{WebConfig.class};}/*  * 将DispatchServlet映射到"/" * (non-Javadoc) * @see org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#getRootConfigClasses() */@Overrideprotected String[] getServletMappings() {return new String[] {"/"};}}

简单来说,tomcat会自动加载实现AbstractAnnotationConfigDispatcherServletInitializer 类

1.配置DispatcherServlet请求映射

2.配置ApplicationContext

2.配置webApplicationContext

package com.jack.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.ViewResolver;import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;import org.springframework.web.servlet.config.annotation.EnableWebMvc;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;import org.springframework.web.servlet.view.InternalResourceViewResolver;/**加载Web相关的bean *  * @author Administrator * */@Configuration@EnableWebMvc //相当于<mvc:annotation-driven> 启用SpringMVC@ComponentScan("com.jack")     //启用组件扫描包名public class WebConfigextends WebMvcConfigurerAdapter{/** * 配置JSP视图解析器 * @return * /WEB-INF/views/home.jsp */@Beanpublic ViewResolver viewResolver(){InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix("/WEB-INF/views/");resolver.setSuffix(".jsp");resolver.setExposeContextBeansAsAttributes(true);return resolver;}/** * 新的WebConfig类还扩展了WebMvcConfigurerAdapter并重写了其configureDefaultServletHandling()方法。通过调用DefaultServlet-HandlerConfigurer的enable()方法, * 我们要求DispatcherServlet将对静态资源的请求转发到Servlet容器中默认的Servlet上, * 而不是使用DispatcherServlet本身来处理此类请求。 * (non-Javadoc) * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#configureDefaultServletHandling(org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer) */@Overridepublic void configureDefaultServletHandling( DefaultServletHandlerConfigurer configurer){configurer.enable();}}
总结:@EnableWebMvc 启动SpringMVC @ComponentScan 配置扫描bean,

在配置视图解析器和静态资源过滤给默认Servlet

package com.jack.config;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.ComponentScan.Filter;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.FilterType;import org.springframework.web.servlet.config.annotation.EnableWebMvc;@Configuration@ComponentScan(basePackages={"com.jack"},excludeFilters={@Filter(type=FilterType.ANNOTATION, value=EnableWebMvc.class)})public class RootConfig {}
开始写简单的控制类

package com.jack.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;@Controller //声明为一个控制器public class HomeController {@RequestMapping(value={"/","/homepage"}, method=RequestMethod.GET) //处理"/"的GET请求public String home(){return "home"; //视图名为home}}

总结:

1.注意在类上写上@Controller

2.在方法写url路径的映射@RequestMapping(value={"/","homepage"}) 表示 "/" 和 "homepage" 都会被这个控制器处理

3.返回"home"会被视图解析器处理变成/WEB-INF/views/home.jsp

测试类:

package com.jack.controller;import static org.junit.Assert.assertEquals;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;import org.junit.Test;import org.springframework.test.web.servlet.MockMvc;public class HomeControllerTest {@Testpublic void testHomePage() throws Exception{HomeController controller = new HomeController();assertEquals("home", controller.home());}/** *  * 这里需要注意一下standaloneSetup是静态方法 * get("/") view() 抽象类中会有很多静态方法,虽然 * 抽象不能new,但是方法可以创建对象 * @throws Exception */@Testpublic void testHomePageRequest() throws Exception{HomeController controller = new HomeController();MockMvc mockMvc = standaloneSetup(controller).build();mockMvc.perform(get("/homepage")).andExpect(view().name("home"));}}

总结:

1.第一个方法是简单方法测试,第二个是模拟请求测试

2.注意standaloneSetup() 和 get() 以及view()都是静态方法

3.其实你发现它,模拟操作过程,

MockMvcBuilders(设置)——》MockMvcRequestBuilders(请求)--》MockMvcResultMatchers(匹配视图)


写个一个类模拟数据库数据

首先接口:

package com.jack.data;import java.util.List;public interface SpittleRepository {List<Spittle> findSpittles(long max, int count);}
  实现类
package com.jack.data.impl;import java.util.ArrayList;import java.util.Date;import java.util.List;import org.springframework.stereotype.Component;import com.jack.data.Spittle;import com.jack.data.SpittleRepository;@Componentpublic class SpittleRepositoryImpl implements SpittleRepository{@Overridepublic List<Spittle> findSpittles(long max, int count) {List<Spittle> list = new ArrayList<Spittle>();Spittle sp1 = new Spittle("第一个信息", new Date(),100.00, 40.102);Spittle sp2 = new Spittle("第二个信息", new Date());Spittle sp3 = new Spittle("第三个信息", new Date());Spittle sp4 = new Spittle("第四个信息", new Date());list.add(sp4);list.add(sp3);list.add(sp1);list.add(sp2);return list;}}

控制类:

package com.jack.controller;import java.util.List;import java.util.Map;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import com.jack.data.Spittle;import com.jack.data.SpittleRepository;@Controller@RequestMapping("/spittles")public class SpittleController {private SpittleRepository spittleRepository;@Autowiredpublic SpittleController(SpittleRepository spittleRepository){this.spittleRepository = spittleRepository;}/*@RequestMapping(method=RequestMethod.GET)public String spittles(Model model) {//将spittle添加到模型中//方式一//注意这里没有key,它可以根据List<Spittle> 推断 key = spittleListmodel.addAttribute(spittleRepository.findSpittles(Long.MAX_VALUE, 20));//方式二//显式指定keymodel.addAttribute("spittleList", spittleRepository.findSpittles(Long.MAX_VALUE, 20));//返回视图名return "spittles";}*///方式三//它会根据请求/spittles,判断 视图为spittles/*@RequestMapping(method=RequestMethod.GET)public List<Spittle> spittles(){return spittleRepository.findSpittles(Long.MAX_VALUE, 20);}*///方法四@RequestMapping(method=RequestMethod.GET)public String spittles(Map model){model.put("spittleList", spittleRepository.findSpittles(Long.MAX_VALUE, 20));return "spittles";}}

总结:

1.这么多方法可以表示说明它有依据

2.依据请求路径获取视图

3.根据返回数据推断key

4.model底层是Map数据格式

mock测试类

package com.jack.controller;import static org.hamcrest.core.IsCollectionContaining.hasItems;//这要引入新的mockito-all.jarimport static org.mockito.Mockito.mock;import static org.mockito.Mockito.when;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;import java.util.ArrayList;import java.util.Date;import java.util.List;import org.junit.Test;import org.springframework.test.web.servlet.MockMvc;import org.springframework.web.servlet.view.InternalResourceView;import com.jack.data.Spittle;import com.jack.data.SpittleRepository;public class SpittleControllerTest {@Testpublic void shouldShowRecentSpittles() throws Exception{//创建模拟数据List<Spittle> expectedSpittles = createSpittleList(20);//模拟的类SpittleRepository mockRepository = mock(SpittleRepository.class);//模拟类中的方法,只要是调用findSpittles就返回 expectedSpittles数据when(mockRepository.findSpittles(Long.MAX_VALUE, 20)).thenReturn(expectedSpittles);//往控制类注入数据类SpittleController controller = new SpittleController(mockRepository);//设置模拟的controllerMockMvc mockMvc = standaloneSetup(controller).setSingleView( //表示不解析new InternalResourceView("/WEB-INF/views/spittles.jsp")).build();//请求路径/spittlesmockMvc.perform(get("/spittles")).andExpect(view().name("spittles")) //判断视图是否为spittles.andExpect(model().attributeExists("spittleList")) //是否存在这个属性ID.andExpect(model().attribute("spittleList", hasItems(expectedSpittles.toArray())));  //判断数据是否一致}private List<Spittle> createSpittleList(int count) {List<Spittle> spittleList = new ArrayList<Spittle>();for(int i=0; i< count; i++) {spittleList.add(new Spittle("Spittle" + i, new Date()));}return spittleList;}}

总结:

1.引用包Mockito

2.发现测试模拟都是静态类,不熟悉都不知道在哪个包下,很尴尬

import static org.hamcrest.core.IsCollectionContaining.hasItems;
//这要引入新的mockito-all.jar
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;

编写spittles.jsp文件

<%@ tagliburi="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ page session="false" %><%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>RecentSpittles</title><link rel="stylesheet" type="text/css"href="<c:url value="/resources/style.css"/>"></head><body><h1>Recent Spittles</h1><c:forEach items="${spittleList }" var="spittle"><li id="spittle_<c:out value="spittle.id"/>"><div class="spittleMessage"><c:out value="${spittle.message}"></c:out></div><div><span class="spittleTime"><c:out value="${spittle.time }"/></span><span class="spittleLocation">(<c:out value="${spittle.latitude }"/>,<c:out value="${spittle.longitude }"></c:out>)</span></div></li></c:forEach></body></html>

总结:

1、这里要引用jstl-1.2.jar包

2、同时要添加这个一句话<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>不然中文乱码

3、当要用外部包的标签的时候首先导入uri,设置前缀prefix 例如 <%@ tagliburi="http://java.sun.com/jsp/jstl/core" prefix="c" %>

4、"" 里面可以设置标签能够识别,例如:<li id="spittle_<c:out value="spittle.id"/>">

5、对于forEach items="${spittleList}" 遍历的属性的key,而var="spittle"遍历处理的单个对象,注意${}是指在引号内

6、对于对象的属性直接可以用对象.属性的来获取值

7、对于jsp输出标签为<c:out value="输入内容"/>

效果为:



5.2 接受请求的输入

传入的方式:

  • 查询参数(Query Paramter)
  • 表单参数(Form Parameter)
  • 路径变量(Path Variable)

5.2.1处理查询参数

测试类:

@Test public void shouldShowPagedSpittles() throws Exception {List<Spittle> expectedSpittles = createSpittleList(50);SpittleRepository mockRepository = mock(SpittleRepository.class);when(mockRepository.findSpittles(238900, 50)).thenReturn(expectedSpittles);SpittleController controller = new SpittleController(mockRepository);MockMvc mockMvc = standaloneSetup(controller).setSingleView(new InternalResourceView("/WEB-INF/views/spittles.jsp")).build();mockMvc.perform(get("/spittles?max=238900&count=50")).andExpect(view().name("spittles")).andExpect(model().attributeExists("spittleList")).andExpect(model().attribute("spittleList", hasItems(expectedSpittles.toArray())));}
总结:在路径后面 加上 ?+键值对 + 连接符(&)+键值对 例如  /spittles?max=238900&count=50

Controller类:

package com.jack.controller;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 com.jack.data.SpittleRepository;@Controller@RequestMapping("/spittles")public class SpittleController {private SpittleRepository spittleRepository;private static final String MAX_LONG_AS_STRING = Long.MAX_VALUE+"";@Autowiredpublic SpittleController(SpittleRepository spittleRepository){this.spittleRepository = spittleRepository;}@RequestMapping(method=RequestMethod.GET)//@RequestParam("max") long max,@RequestParam("count") int countpublic String spittles(Model model, @RequestParam(value="max", defaultValue=MAX_LONG_AS_STRING) long max,@RequestParam(value="count", defaultValue="20") int count) {//注意这里没有key,它可以根据List<Spittle> 推断 key = spittleListmodel.addAttribute(spittleRepository.findSpittles(max, count));//返回视图名return "spittles";}}

总结:用注解@RequestParam,可以指定默认值,defaultValue ,注意defaultValue是字符串,所以先转成字符串,再转成目标类型

5.1.2.路径传值:

测试方法:

@Testpublic void testSpitte() throws Exception{Spittle expectedSpittle = new Spittle("Hello", new Date());SpittleRepository mockRepository = mock(SpittleRepository.class);when (mockRepository.findOne(123456)).thenReturn(expectedSpittle);SpittleController controller = new SpittleController(mockRepository);MockMvc mockMvc = standaloneSetup(controller).build();mockMvc.perform(get("/spittles/123456")).andExpect(view().name("spittle")).andExpect(model().attributeExists("spittle")).andExpect(model().attribute("spittle", expectedSpittle));}
控制类的方法
@RequestMapping(value="/{spittleId}", method=RequestMethod.GET)public String spittle(@PathVariable("spittleId") long spittleId,Model model){model.addAttribute(spittleRepository.findOne(spittleId));return "spittle";}

spittle.jsp

<%@ tagliburi="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ page session="false" %><%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>RecentSpittles</title><link rel="stylesheet" type="text/css"href="<c:url value="/resources/style.css"/>"></head><body><h1>Recent Spittle</h1><div class="spittleView"><div class="spittleMessage"><c:out value="${spittle.message }"></c:out></div><div><span class="spittleTime"><c:out value="${spittle.time }"></c:out></span></div></div></body></html>
SpittleRepository.java 接口增加方法

Spittle findOne(long i);

SpittleRepositoryImpl.java 实现接口方法

@Overridepublic Spittle findOne(long i) {return new Spittle("第一个微博" , new Date(), 100.0,100.0);}
结果:


5.1.3.表单传递数据

测试类:

package com.jack.controller;//这要引入新的mockito-all.jarimport static org.mockito.Mockito.atLeastOnce;import static org.mockito.Mockito.mock;import static org.mockito.Mockito.verify;import static org.mockito.Mockito.when;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;import org.junit.Test;import org.springframework.test.web.servlet.MockMvc;import com.jack.data.Spitter;import com.jack.data.SpitterRepository;public class SpittlerControllerTest {@Testpublic void shouldShowRegistration() throws Exception{SpittlerController controller = new SpittlerController();MockMvc mockMvc = standaloneSetup(controller).build();mockMvc.perform(get("/spittler/register")).andExpect(view().name("registerForm"));}@Test public void shouldProcessRegistration() throws Exception {SpitterRepository mockRepository = mock(SpitterRepository.class); Spitter unsaved =new Spitter("Jack", "Bauer", "jbauer", "24hours");Spitter saved = new Spitter(24L,"Jack", "Bauer", "jbauer", "24hours");when(mockRepository.save(unsaved)).thenReturn(saved);SpittlerController controller =new SpittlerController(mockRepository);MockMvc mockMvc = standaloneSetup(controller).build();mockMvc.perform(post("/spitter/register").param("firstName", "Jack").param("lastName", "Bauer").param("username", "jbauer").param("password", "24hours")).andExpect(redirectedUrl("/spitter/jbauer"));verify(mockRepository, atLeastOnce()).save(unsaved); //校验保存情况}}
总结:

1、总会发现老外首先写的测试类,然后才是写代码,测试驱动,可以学习一下

2、注册过程是,首先显示一个表单页(registerForm.jsp)——》处理表单请求控制器("/spitter/register")--》简短的呈现页 (profile.jsp)

3、测试类差不多就是静态方法,链式方法

4、redirectedUrl("/spitter/jbauer") 重定向防止重复提交

5、verify验证repository保存方法,是否正确

控制类

package com.jack.controller;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 com.jack.data.Spitter;import com.jack.data.SpitterRepository;@Controller@RequestMapping("/spitter")public class SpittlerController {private SpitterRepository spitterRepository;public SpittlerController(){}@Autowired public SpittlerController(SpitterRepository spitterRepository){this.spitterRepository = spitterRepository;}@RequestMapping(value = "/register", method=RequestMethod.GET)public String showRegistrationForm(){return "registerForm";}@RequestMapping(value="/register", method=RequestMethod.POST)public String processRegistration(Spitter spitter){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";}}
总结:

1、虽然请求路径一样,请求方式不一样 ,例如两个register

2、redirect:/spitter/ 重定向方法

3、最后返回视图profile

package com.jack.data;public interface SpitterRepository {Spitter save(Spitter spitter);Spitter findByUsername(String username);}
package com.jack.data.impl;import org.springframework.stereotype.Component;import com.jack.data.Spitter;import com.jack.data.SpitterRepository;@Componentpublic class SpitterRepositoryImpl implements SpitterRepository{@Overridepublic Spitter save(Spitter spitter) {System.out.println("保存成功");return null;}@Overridepublic Spitter findByUsername(String username) {Spitter spitter =new Spitter("Jack", "Bauer", "jbauer", "24hours");return spitter;}}

总结:这里没有具体实现数据库交互
实体类:

package com.jack.data;import org.apache.commons.lang3.builder.EqualsBuilder;import org.apache.commons.lang3.builder.HashCodeBuilder;public class Spitter {private long l;private String firstName;private String lastName;private String username;private String password;public Spitter() {super();// TODO Auto-generated constructor stub}public Spitter(String firstName, String lastName, String username, String password) {this.firstName = firstName;this.lastName = lastName;this.username = username;this.password = password;}public Spitter(long l, String firstName, String lastName, String username, String password) {this.l = l;this.firstName = firstName;this.lastName = lastName;this.username = username;this.password = password;}public String getFirstName() {return firstName;}public String getLastName() {return lastName;}public String getUsername() {return username;}public String getPassword() {return password;}public void setFirstName(String firstName) {this.firstName = firstName;}public void setLastName(String lastName) {this.lastName = lastName;}public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}public long getL() {return l;}public void setL(long l) {this.l = l;}@Overridepublic boolean equals(Object obj) {return EqualsBuilder.reflectionEquals(this, obj, "firstName", "lastName");}@Overridepublic int hashCode() {return HashCodeBuilder.reflectionHashCode(this, "firstName", "lastName");}@Overridepublic String toString() {return "Spitter [l=" + l + ", firstName=" + firstName + ", lastName=" + lastName + ", username=" + username+ ", password=" + password + "]";}}

profile.jsp

<%@ tagliburi="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ page session="false" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Spittr</title><link rel="stylesheet" type="text/css"href="<c:url value="/resources/style.css"/>"></head><body><h1>Your Profile</h1><c:out value="${spitter.username }"></c:out><br/><c:out value="${spitter.firstName }"></c:out><c:out value="${spitter.lastName }"></c:out></body></html>


registerForm.jsp
<%@ tagliburi="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ page session="false" %><%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>RegisterPage</title><link rel="stylesheet" type="text/css"href="<c:url value="/resources/style.css"/>"></head><body><h1>注册</h1><form action="" method="POST">First Name:<input type="text" name="firstName"/><br/>Last Name:<input type="text" name="lastName" /> <br/>UserName: <input type="text" name="username"/><br/>Password: <input type="password" name="password"/><br/><input type="submit" value="Register" /></form></body></html>

5.3校验表单

Spring 校验 Java Validation API 又称 JSR-303
Hibernate Validator
Java校验API
javax.validation.constraints包下

  • @AssertFalse   所注解的元素必须是Boolean类型,并且值为false
  • @AssertTrue   所有注解的元素必须是Boolean类型, 并且值为true
  • @DecimalMax 所有注解的元素必须是数字,并且它的值要小于或等于给定的BigDecimalString值
  • @DecimalMin 所注解的元素必须是数字,并且它的值要大于或者等于给定的BigDecimalString值
  • @Digits 所注解的元素必须是数字,并且它的值必须指定位数
  • @Future 所注解的元素的值必须是一个将来的日期
  • @Max 所注解的元素必须是数字,并且它的值要小于或等于给定的值
  • @Min 所注解的元素必须是数字,并且它的值要大于或等于给定的值
  • @NotNull 所注解元素的值必须不能为null
  • @Null 所注解元素的值必须为null
  • @Past 所注解的元素的值必须是一个已过去的日期
  • @Pattern 所注解的元素的值必须匹配给定的正则表达式
  • @Size 所注解的元素的值必须是String、集合或数组,并且它的长度要符合给定的范围

引入jar

<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.4.1.Final</version>
</dependency>


修改Spitter.java

        @NotNull
@Size(min=2, max=30)
private String firstName;
@NotNull
@Size(min=2, max=30)
private String lastName;
@NotNull
@Size(min=5, max=16)
private String username;
@NotNull
@Size(min=5, max=25)
private String password;

修改控制类

//不满足要求自动跳转表单页

@RequestMapping(value="/register", method=RequestMethod.POST)
public String processRegistration( @Valid Spitter spitter,
Errors errors
){
if(errors.hasErrors()) {
return "registerForm";
}

spitterRepository.save(spitter);

return "redirect:/spitter/" + spitter.getUsername();
}

总结:影响最深就是先写测试类,然后写代码。测试驱动

用例Demo

点击打开链接

阅读全文
0 0
原创粉丝点击