springMVC第二章数据校验和控制层传参
知识点一:使用JSR303框架完成数据校验工作
1.导入数据校验所需要的jar包
2.在springMVC-servlet文件中注册所需要的驱动
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="com.xt.handler"></context:component-scan>
<!-- 启动校验驱动 -->
<mvc:annotation-driven/>
<!-- 注入校验bean -->
<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"></bean>
</beans>
3.创建pojo实体类,使用JSR303标准实现数据校验@Pattern@Range...
package com.xt.pojo;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Range;
public class Survey {
private String week;
@Pattern(regexp="\\w{6,12}",message="姓名必须在6~12位")
private String name;
@Range(min=18,max=45,message="年龄必须在18~45之间")
private int age;
@Pattern(regexp="\\d{11}",message="电话必须为11位")
private String tel;
private String answer1;
private String answer2;
private String answer3;
public Survey() {
super();
// TODO Auto-generated aconstructor stub
}
public Survey(String week, String name, int age, String tel, String answer1, String answer2, String answer3) {
super();
this.week = week;
this.name = name;
this.age = age;
this.tel = tel;
this.answer1 = answer1;
this.answer2 = answer2;
this.answer3 = answer3;
}
public String getWeek() {
return week;
}
public void setWeek(String week) {
this.week = week;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getAnswer1() {
return answer1;
}
public void setAnswer1(String answer1) {
this.answer1 = answer1;
}
public String getAnswer2() {
return answer2;
}
public void setAnswer2(String answer2) {
this.answer2 = answer2;
}
public String getAnswer3() {
return answer3;
}
public void setAnswer3(String answer3) {
this.answer3 = answer3;
}
@Override
public String toString() {
return "Survey [week=" + week + ", name=" + name + ", age=" + age + ", tel=" + tel + ", answer1=" + answer1
+ ", answer2=" + answer2 + ", answer3=" + answer3 + "]";
}
}
4.在handler中,接受页面请求,进行数据校验。
- @Valid:声明该对象需要进行数据校验
- @ModelAttribute("survey") 将jsp页面传回来的数据封装到survey中,
- 由于 @ModelAttribute("survey")前面有@Valid,所以封装好的survey对象也包含了校验后的信息。
- BindingResult bindingResult用于收集错误信息,当有错误信息时,hasError()方法为true。
package com.xt.handler;
import javax.validation.Valid;
import javax.websocket.server.PathParam;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
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.xt.pojo.Survey;
@Controller
@RequestMapping("/survey")
public class SurveyHandler {
@RequestMapping(value="/{week}/check")
public String checkMessage(@Valid @ModelAttribute("survey") Survey survey,@PathVariable String week,BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
System.out.println("error");
return "/survey.jsp";
} else {
System.out.println("success");
return "/success.jsp";
}
}
}
5.创建survey.jsp,将数据提交到handler中
- 注册form标签库:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
- 从handler中获取封装好的survey对象,该对象中包含了错误信息:
form:form modelAttribute="survey"
- 如果有错误信息将错误信息打印:
<span><form:errors path="name"/></span><br/>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>survey</title>
</head>
<body>
<form:form modelAttribute="survey" action="/springMVCT2/survey/201907/check" method="post">
<fieldset>
<legend>读者调查问卷</legend>
<!-- 基本信息 start -->
<fieldset>
<legend>基本信息</legend>
<table>
<tr><td>姓名</td>
<td><input name="name"><span><form:errors path="name"/></span><br/></td>
</tr>
<tr><td>年龄</td>
<td><input name="age"><span><form:errors path="age"/></span><br/></td>
</tr>
<tr><td>联系电话</td>
<td><input name="tel"><span><form:errors path="tel"/></span><br/></td>
</tr>
</table>
</fieldset>
<!-- 基本信息 end -->
<!-- 调查信息 start -->
<fieldset>
<legend>调查信息</legend>
<b>您喜欢的本期封面和内容版式设计吗?</b><br/>
<textarea rows="3" cols="100" name="answer1"></textarea><br/>
<b>您喜欢的本期的哪几篇文章?</b><br/>
<textarea rows="3" cols="100" name="answer2"></textarea><br/>
<b>您不喜欢的本期的哪几篇文章?</b><br/>
<textarea rows="3" cols="100" name="answer3"></textarea>
</fieldset>
<!-- 调查信息 end -->
<center><input type="submit" value="提交调查"></center>
</fieldset>
</form:form>
</body>
</html>
知识点二:使用ModelAndView对象进行控制层传参
ModelAndView mv = new ModelAndView("/survey.jsp");
return mv;
- 注意:
@Valid @ModelAttribute("survey") Survey survey
和BindingResult bindingResult
之间不能添加其它注解。
package com.xt.handler;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
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.servlet.ModelAndView;
import com.xt.pojo.Survey;
@Controller
@RequestMapping("/survey")
public class SurveyHandler {
@RequestMapping(value="/{week}/check",method=RequestMethod.POST)
public ModelAndView checkMessage(HttpServletRequest req, @PathVariable("week") String week,@Valid @ModelAttribute("survey") Survey survey,BindingResult bindingResult) {
survey.setWeek(week);
if (bindingResult.hasErrors()) {
System.out.println("success");
ModelAndView mv = new ModelAndView("/survey.jsp");
return mv;
} else {
System.out.println("error");
ModelAndView mv = new ModelAndView("/success.jsp");
mv.addObject("week",survey.getWeek());
// mv.addObject("name",survey.getName());
req.setAttribute("name", survey.getName());
mv.addObject("age",survey.getAge());
mv.addObject("tel",survey.getTel());
mv.addObject("answer1",survey.getAnswer1());
mv.addObject("answer2",survey.getAnswer2());
mv.addObject("answer3",survey.getAnswer3());
System.out.println("success");
return mv;
}
}
}
知识点三:给request,session作用域赋值
方法:直接在public ModelAndView checkMessage(HttpServletRequest req)
参数中添加HttpServletRequest req,HttpSession sessions
。
知识点四:利用form标签库从model中读取数据
`
传统方式中,我们生成复选框,下拉选框,都直接在jsp页面编写好html代码,
但是这种方式,不利于代码的可扩展性,比如省份下拉框中,如果新增了其他的省份,
需要修改很多处的代码,给代码的可维护性大大降低。
因此我们一般在程序设计中,一般采用从数据库读出的方式,再结合标签来生成相应的代码。
以生成省份下拉框为例进行演示。
`
编写Province pojo类
package com.xtkj.pojo;
public class Province {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Province() {
super();
// TODO Auto-generated constructor stub
}
public Province(int id, String name) {
super();
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Province [id=" + id + ", name=" + name + "]";
}
}
编写service层,将查询到的provinces返回给controler层
package com.xtkj.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.xtkj.pojo.Province;
@Service("userService")相当于<bean id="userService" class="...."></bean>
@Service("userService")引号里面的内容<bean里面的id="userService">
@Service("userService")
public class UserService {
public List<Province> getProvince(){
List<Province> list = new ArrayList<Province>();
list.add(new Province(1, "湖北"));
list.add(new Province(2, "湖南"));
list.add(new Province(3, "广西"));
list.add(new Province(4, "广东"));
return list;
}
}
@Service("userService")
就类似于@Controller
在将service注入到handler中
有两种方法:
1.@Autowired 自动注入,需要@Service("userService")
与private UserService userService;
对象名一致
2.@Resource(name="userService")//获取指定id的bean,通过service名称注入
package com.xtkj.handler;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import com.xtkj.pojo.Province;
import com.xtkj.pojo.User;
import com.xtkj.service.UserService;
@Controller
@RequestMapping("/")
public class UserHandler {
@Autowired
//@Resource(name="userService")//获取指定id的bean
private UserService userService ;
@RequestMapping("/regist")
public String regist(@Valid @ModelAttribute("user") User user,BindingResult br){
if(br.hasErrors()){
return "/regist.jsp";
}else{
System.out.println("account="+user.getAccount());
return "/welcome.jsp";
}
}
@RequestMapping("/goRegist")
public String goRegist(HttpServletRequest req){
System.out.println("userService="+userService);
List<Province> province = userService.getProvince();
req.setAttribute("provinces", province);
req.setAttribute("user", new User());
return "/regist.jsp";
}
}
注意:由于进入注册页面就需要有省份下拉框的信息,所以,在进入regist.jsp之前首先应该
调用查询方法,然后再请求转发给jsp页面。这样jsp页面才能获取Province数据,由此,就有了
public String goRegist(HttpServletRequest req){...}
方法。
编写jsp页面,使用<form:>
省份:<form:select path="province">
<form:options items="${provinces }" itemLabel="name" itemValue="id"/>
</form:select><br/>
<input type="submit" value="注册"/>
</form:form>
完整代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'regist.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<style type="text/css">
span{
color:red;
}
</style>
</head>
<body>
<form:form modelAttribute="user" action="regist.form">
账号:<input type="text" name="account" value="${user.account }"/><span><form:errors path="account"/></span><br/>
密码:<input type="password" name="password" value="${user.password }"/><span><form:errors path="password"/></span><br/>
头像:<img src="img/wa.png"/><br/>
省份:<form:select path="province">
<form:options items="${provinces }" itemLabel="name" itemValue="id"/>
</form:select><br/>
<input type="submit" value="注册"/>
</form:form>
</body>
</html>
知识点五:在SpringMVC中访问静态资源
由于在web.xml中DispatcherServlet的url-pattern为'/'拦截一切资源访问,所以jsp页面请求访问静态资源也会被拦截。解决办法有以下两种:
方法一:修改<url-pattern>
<!-- springMVC核心 -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<!-- <url-pattern>/</url-pattern> -->
<url-pattern>*.form</url-pattern>
</servlet-mapping>