属性copy方法
BeanUtils.copyProperties(被copy对象,目标对象);
@controller中的方法返回值
返回ModelAndView
方法结束之前,需要定义ModelAndView,将model和view分别进行设置。
1 |
|
返回 stringe
1、表示返回逻辑视图名。
真正视图(isp路径)=前缀+逻辑视图名+后缀+
2、redirect
return “redirect:findStudentsList”;
3、forward
return “forward:findStudentsList”;
返回void
相当于普通的servlet,参数中添加request和response
@controller中的方法参数
一般的HttpServletRequest、HttpServletResponse、HttpSession
另外还有Model、ModelMap
model是一一个 接口,modelMap 是一个接口实现。
作用:将model数据填充到request域。@RequestParam
通过@RequestParam对简单类型的参数进行绑定。如果不使用,要求参数名必须和传入的参数(key/value)中的key相同,
参数:required=true 指定该参数不能为null
defaultValue=””设置默认值,如果参数为null,则使用该默认值
1 |
|
如果参数为自定义对象,那么前台传入的参数需要和对象中的属性名一致
自定义参数绑定
对象
1
2
3public class Person {
private String address;
private User user;1
2
3
4
5
6
7<!-- 页面 -->
<form action="saveUserfz">
<input type="text" name="user.uid"/><br>
<input type="text" name="user.uname"/><br>
<input type="text" name="address"/><br>
<input type="submit" value="tijiao"/>
</form>1
2
3
4
5
public String saveUser(Model model,Person p) {
model.addAttribute("u", p);
return "index";
}list
1
2
3
4
5public class Person {
private String address;
private User user;
private List<User> ulist;1
2
3
4
5
6
7
8<form action="saveUserfzjh">
<input type="text" name="address"/><br>
用户一:<input type="text" name="ulist[0].uid"/><br>
<input type="text" name="ulist[0].uname"/><br>
用户二:<input type="text" name="ulist[1].uid"/><br>
<input type="text" name="ulist[1].uname"/><br>
<input type="submit" value="提交"/>
</form>1
2
3
4
5
public String saveUserfzjh(Model model,Person p) {
model.addAttribute("u", p);
return "index";
}set
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class UserVo {
private Set<User> userSet = new HashSet<>();
public UserVo() {
userSet.add(new User());
userSet.add(new User());
}
public Set<User> getUserSet() {
return userSet;
}
public void setUserSet(Set<User> userSet) {
this.userSet = userSet;
}
}1
2
3
4<form action="/echoSet" method="post">
<input name="userList[0].name" value="张三" type="text"/>
<input name="userList[0].age" value="21" type="text"/>
</form>1
2
3
4
5
6
public String echoSet(UserVo userVo){
Set<User> userSet = userVo.getUserSet();
return JSON.toJSONString(userSet);
}map
1
2
3
4Public class QueryVo {
private Map<String, Student> itemInfo = new HashMap<String, Student>();
//get/set方法..
}1
2
3
4
5
6
7<tr>
<td>学生信息:</td>
<td>
姓名:<input type="text" name="itemInfo['name']"/>
年龄:<input type="text" name="itemInfo['price']"/>
</td>
</tr>
自定义参数转换器
- 新建一个类实现Converter接口
1 | public class CustomDateConverter implements Converter<String,Date>{ |
在springmvc.xml中配置:
1 | <mvc:annotation-driven |
乱码解决
post乱码解决:
在web.xml中添加过滤器
1 | <filter> |
get乱码解决:
修改tomcat配置文件添加编码与工程编码一致,如下:
1 | <Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" |
另外-种方法对参数进行重新编码:
1 | String userName = |
校验器
导入jar包
hibernate-validator-6.0.17.Final.jar
hibernate-validator-annotation-processor-6.0.17.Final.jar
hibernate-validator-cdi-6.0.17.Final.jar
springmvc.xml文件配置自定义校验器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27<!-- 将校验器注入处理器适配器 -->
<mvc:annotation-driven
conversion-service="conversionService" validator="validator"/>
<!--校验器-->
<bean id= "validator"
class= "org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<!-- hibernate校验器 -->
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<!--指定校验使用的资源文件, 在文件中配置校验错误信息,如果不指定则默认使用classpath下的ValidationMessages.properties -->
<property name="validationMessageSource" ref="messageSource" />
</bean>
校验错误信息配置文件-- >
<bean id="messageSource”
class="org.springframework.context.support.ReloadableResourceBundLeMessageSource">
<property name="basenames">
<list>
<!--外部properties资源文件名-->
<value>classpath:CustomValidationMessages</value>
</list>
</property>
<!--资源文件编码格式-->
<property name= "fileEncodings" value= "utf-8" />
<!--对资源文件内容缓存时间,单位秒-->
<property name= "cacheSeconds" value= "120">
</bean>
CustomValidationMessages.properties
1 | items.name.length.error=请输入1到30个字符的商品名称 |
entity中:
1 | public class Items { |
在需要校验的pojo前边添加@Validated,在需要校验的pojo后边添加BindingResult bindingResult接收校验出错信息
注意: @Validated和BindingResult bindingResult是配对出现,并且形参顺序是固定的(一前一后)。
1 |
|
定义多个校验分组(其实是一个java接口),分组中定义有哪些规则。每个controller方法使用不同的校验分组。
那就来两个接口
1 | public interface ValidGroup1 { |
然后在实体类需要校验的属性上添加groups={ValidGroup1.class},将此校验方式分配到ValidGroup1组
1 | //groups:此校验属于哪个分组,groups可以定义多个分组 |
再然后在controller方法的参数中添加@Validated(value={ValidGroup1.class})指定校验规则为ValidGroup1组
1 | public String updateStudent( Student student, BindingResult bindingResult) throws Exception { |
数据回显
Student实体类对象数据传入controller中的方法之后,springmvc自动将其放入request作用域中,key为student(默认类名首字母小写)
怎么样自定义这个key呢
使用在Student student参数之前@ModelAttribute(“key”)就可以指定自己喜欢的key
1 | public String updateStudent( Student student, BindingResult bindingResult) throws Exception { |
@ModelAttribute(“key”)还有一个作用就是写在某个方法上,作用是将这个方法的返回值放到request作用域中,并且指定key值为你自己写的key.
当然,还有最简单的一个方法就是直接使用Model来将这个对象加进request作用域中不用任何注解
1 | public String updateStudent(Model model Student student, BindingResult bindingResult) throws Exception { |
!!注意:::@ModelAttribute(“key”)只能作用在包装对象上,不能用在基本数据类型上,基本数据类型只能用 model.addAttribute()来回显
全局异常处理器
首先自定义一个异常类CustomException.java:
1 | public class CustomException extends Exception { |
再写一个全局异常处理器
思路:
系统遇到异常,需要在程序中手动抛出,dao 抛给service ,service 给controller, controller 抛给前端控制器,前端控制器调用全局异常处理器。全局异常处理器处理思路:
解析出异常类型。
如果该异常类型是系统自定义的异常,直接取出异常信息,在错误页面展示
如果该异常类型不是系统自定义的异常,构造一个自定义的异常信息为“未知错误”并转发给error页面
1 | public class CustomExceptionResolver implements HandlerExceptionResolver { |
在springmvc.xml文件中配置这个全局异常处理器
1 | <!--配置自定义全局异常处理器 只要实现HandlerExceptionResolver接口就是全局异常处理器 --> |
使用时直接
1 | throw new CustomException("异常信息"); |
RESTful风格
1 | ///itemsView/{id}里边的{id}表示将这个位置的参数传到PathVariable指定名称中,并使用Integer id接收。 |
在web.xml中配置restful的前端控制器
1 | <!-- 前端控制器 --> |
但是
1 | <mvc:resources location="/js/" mapping="/js/**"/> |
context:component-scan mvc:annotation-driven的区别
<context:component-scan/>只做扫描注解包下bean的工作,让bean生效。在这个基础上配置jsp的视图解析其实就可以正常访问jsp视图如果没有
<mvc:annotation-driven/>你就无法实现如接收返回json数据、参数验证、统一异常等功能。