SpringMVC进阶(三)

来源:互联网 发布:mac下html5开发工具 编辑:程序博客网 时间:2024/06/01 09:42
复习:

springmvc框架:
DispatcherServlet前端控制器:接收request,进行response
HandlerMapping处理器映射器:根据url查找Handler。(可以通过xml配置方式,注解方式)
HandlerAdapter处理器适配器:根据特定规则去执行Handler,编写Handler时需要按照HandlerAdapter的要求去编写。
Handler处理器(后端控制器):需要程序员去编写,常用注解开发方式。
Handler处理器执行后结果 是ModelAndView,具体开发时Handler返回方法值类型包括:ModelAndView、String(逻辑视图名)、void(通过在Handler形参中添加request和response,类似原始servlet开发方式,注意:可以通过指定response响应的结果类型实现json数据输出)
View resolver视图解析器:根据逻辑视图名生成真正的视图(在springmvc中使用View对象表示)
View视图:jsp页面,仅是数据展示,没有业务逻辑。

注解开发:
使用注解方式的处理器映射器和适配器:
《!--注解映射器 --》
《beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/》
《!--注解适配器 --》
《beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/》

在实际开发,使用《mvc:annotation-driven》代替上边处理器映射器和适配器配置。

@controller注解必须要加,作用标识类是一个Handler处理器。
@requestMapping注解必须要加,作用:
1、对url和Handler的方法进行映射。
2、可以窄化请求映射,设置Handler的根路径,url就是根路径+子路径请求方式
3、可以限制http请求的方法
映射成功后,springmvc框架生成一个Handler对象,对象中只包括 一个映射成功的method。

注解开发中参数绑定:
将request请求过来的key/value的数据(理解一个串),通过转换(参数绑定的一部分),将key/value串转成形参,将转换后的结果传给形参(整个参数绑定过程)。
springmvc所支持参数绑定:
1、默认支持很多类型,HttpServletRequest、response、session、
model/modelMap(将模型数据填充到request域)
2、支持简单数据类型,整型、字符串、日期。。
只要保证request请求的参数名和形参名称一致,自动绑定成功
如果request请求的参数名和形参名称不一致,可以使用@RequestParam(指定request请求的参数名),@RequestParam加在形参的前边。
3、支持pojo类型
只要保证request请求的参数名称和pojo中的属性名一致,自动将request请求的参数设置到pojo的属性中。
注意:形参中即有pojo类型又有简单类型,参数绑定互不影响。
自定义参数绑定:
日期类型绑定自定义:
定义的Converter《源类型,目标类型》接口实现类,比如:
Converter《String,Date》表示:将请求的日期数据串转成java中的日期类型。
注意:要转换的目标类型一定和接收的pojo中的属性类型一致。
将定义的Converter实现类注入到处理器适配器中。
《mvc:annotation-drivenconversion-service="conversionService"》
《/mvc:annotation-driven》
《!-- conversionService --》
《bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
《!-- 转换器 --》
《property name="converters"》
《list》
《beanclass="cn.itcast.ssm.controller.converter.CustomDateConverter"/》
《/list》
《/property》
《/bean》


springmvc和struts2区别:
springmvc面向方法开发的(更接近service接口的开发方式),struts2面向类开发。
springmvc可以单例开发,struts2只能是多例开发。





2 包装类型pojo参数绑定

2.1 需求
商品查询controller方法中实现商品查询条件传入。

2.2 实现方法
第一种方法:在形参中 添加HttpServletRequestrequest参数,通过request接收查询条件参数。
第二种方法:在形参中让包装类型的pojo接收查询条件参数。
分析:
页面传参数的特点:复杂,多样性。条件包括 :用户账号、商品编号、订单信息。。。
如果将用户账号、商品编号、订单信息等放在简单pojo(属性是简单类型)中,pojo类属性比较多,比较乱。
建议使用包装类型的pojo,pojo中属性是pojo。
2.3 页面参数和controller方法形参定义

页面参数:

商品名称:《input name="itemsCustom.name" /》
注意:itemsCustom和包装pojo中的属性一致即可。

controller方法形参:
public ModelAndView queryItems(HttpServletRequestrequest,ItemsQueryVo itemsQueryVo) throws Exception


public class ItemsQueryVo {
//商品信息
private Items items;
//为了系统 可扩展性,对原始生成的po进行扩展
private ItemsCustom itemsCustom;









3 集合类型绑定

3.1 数组绑定

3.1.1 需求
商品批量删除,用户在页面选择多个商品,批量删除。

3.1.2 表现层实现
关键:将页面选择(多选)的商品id,传到controller方法的形参,方法形参使用数组接收页面请求的多个商品id。


controller方法定义:
@RequestMapping("/deleteItems")
public String deleteItems(Integer[] items_id) throwsException{


页面定义:
《tr》
《td》《input type="checkbox" name="items_id"value="${item.id}"/》《/td》
《td》${item.name }《/td》
《td》${item.price }《/td》
《td》${item.detail }《/td》
《td》《a href="${pageContext.request.contextPath}/items/editItems.action?id=${item.id}"》修改《/a》《/td》

《/tr》







3.2 list绑定
3.2.1 需求
通常在需要批量提交数据时,将提交的数据绑定到list《pojo》中,比如:成绩录入(录入多门课成绩,批量提交),
本例子需求:批量商品修改,在页面输入多个商品信息,将多个商品信息提交到controller方法中。

3.2.2 表现层实现


controller方法定义:
1、进入批量商品修改页面(页面样式参考商品列表实现)
2、批量修改商品提交
使用List接收页面提交的批量数据,通过包装pojo接收,在包装pojo中定义list《pojo》属性


public class ItemsQueryVo {
//商品信息
private Items items;
//为了系统 可扩展性,对原始生成的po进行扩展
private ItemsCustom itemsCustom;
//批量商品信息
private List《ItemsCustom》 ItemsList;




//批量修改商品提交
//通过ItemsQueryVo接收批量提交的商品信息,将商品的信息存储到ItemsQueryVo的itemsList属性中
@RequestMapping("/editItemsAllSubmit")
public String editItemsAllSubmit(ItemsQueryVo itemsQueryVo)throws Exception{
return "success";
}





页面定义:
《c:forEach items="${itemsList }" var="item"varStatus="status"》
《tr》

《td》《input name="itemsList[${status.index }].name"value="${item.name }"/》《/td》
《td》《input name="itemsList[${status.index }].price"value="${item.price }"/》《/td》
《td》《input name="itemsList[${status.index }].createtime"value="《fmt:formatDate value="${item.createtime}"pattern="yyyy-MM-dd HH:mm:ss"/》"/》《/td》
《td》《input name="itemsList[${status.index }].detail"value="${item.detail }"/》《/td》


《/tr》
《/c:forEach》




3.3 map绑定
也通过在包装pojo中定义map类型属性。

在包装类中定义Map对象,并添加get/set方法,action使用包装对象接收。
包装类中定义Map对象如下:
Public class QueryVo {
private Map《String, Object》 itemInfo = new HashMap《String,Object》();
  //get/set方法..
}



页面定义如下:

《tr》
《td》学生信息:《/td》
《td》
姓名:《inputtype="text"name="itemInfo['name']"/》
年龄:《inputtype="text"name="itemInfo['price']"/》
.. .. ..
《/td》
《/tr》

Contrller方法定义如下:

public String useraddsubmit(Model model,QueryVo queryVo)throwsException{
System.out.println(queryVo.getStudentinfo());
}








4 springmvc校验

4.1 校验理解

项目中,通常使用较多是前端的校验,比如页面中js校验。对于安全要求较高点建议在服务端进行校验。

服务端校验:
控制层conroller:校验页面请求的参数的合法性。在服务端控制层conroller校验,不区分客户端类型(浏览器、手机客户端、远程调用)
业务层service(使用较多):主要校验关键业务参数,仅限于service接口中使用的参数。
持久层dao:一般是不校验的。

4.2 springmvc校验需求

springmvc使用hibernate的校验框架validation(和hibernate没有任何关系)。

校验思路:
页面提交请求的参数,请求到controller方法中,使用validation进行校验。如果校验出错,将错误信息展示到页面。
具体需求:
商品修改,添加校验(校验商品名称长度,生产日期的非空校验),如果校验出错,在商品修改页面显示错误信息。

4.3 环境准备
hibernate的校验框架validation所需要jar包:




hibernate-validator-4.3.0.Final.har
jboss-logging-3.1.0.CR2.jar
validation-api-1.0.0.GA.jar




4.4 配置校验器
《!-- 校验器 --》
《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》   
          《value》classpath:CustomValidationMessages《/value》 
       《/list》  
    《/property》
《!-- 资源文件编码格式 --》
《property name="fileEncodings" value="utf-8" /》
《!-- 对资源文件内容缓存时间,单位秒 --》
《property name="cacheSeconds" value="120" /》
《/bean》




4.5 校验器注入到处理器适配器中

《mvc:annotation-driven conversion-service="conversionService"validator="validator"》《/mvc:annotation-driven》





4.6 在pojo中添加校验规则
在ItemsCustom.java中添加校验规则:

 //校验名称在1到30个字符
   //message提示校验出错所显示的校验信息
   @Size(min=1,max=30,message="{items.name.length.error}")
    private Stringname;

    private Floatprice;

    private Stringpic;

    //非空校验
   @NotNull(message="{items.name.length.isNUll}")
private Date createtime;



4.7 CustomValidationMessages.properties

在CustomValidationMessages.properties配置校验错误信息:

items.name.length.error=请输入1到30个字符的商品名称
items.createtime.isNUll=请输入 商品的生产日期







4.8 捕获校验错误信息
//商品信息修改提交
//在需要校验的pojo的前面添加@Validated,在需要校验的pojo的后面需要添加BindingResultbindingResult接收校验出错信息
// 注意:@Validated和BindingResultbindingResult是配对出现,并且形参顺序是固定的(一前一后)。
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(HttpServletRequestrequest,Integer id,
@Validated ItemsCustom itemsCustom,BindingResultbindingResult)throws Exception {
//获取校验出错信息
if(bindingResult.hasErrors()){
//输出错误信息
List《ObjectError》 allErrors =bindingResult.getAllErrors();
for(ObjectError objectError:allErrors){
System.out.println(objectError.getDefaultMessage());
}
}



4.9 在页面显示校验错误信息


@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(Model model,HttpServletRequestrequest,Integer id,
@Validated ItemsCustom itemsCustom,BindingResultbindingResult)throws Exception {
//获取校验出错信息
if(bindingResult.hasErrors()){
//输出错误信息
List《ObjectError》 allErrors =bindingResult.getAllErrors();
for(ObjectError objectError:allErrors){
System.out.println(objectError.getDefaultMessage());
}
model.addAttribute("allErrors", allErrors);
//出错重新到商品修改页面
return "items/editItems";
}


页面显示错误信息:
《!-- 显示错误信息 --》
${ error.defaultMessage}《br/》




4.10 分组校验
4.10.1 需求
在pojo中定义校验规则,而pojo是被多个controller所共用,当不同的controller方法对同一个pojo进行校验,但是每个controller方法需要不同的校验。

解决方法:
定义多个校验分组(其实是一个java接口),分组中定义有哪些规则
每个controller方法使用不同的校验分组


4.10.2 校验分组
public interface ValidGroup1 {

//接口中不需要定义任何方法,仅是区分不同的校验规则分组
//此分组只校验商品名称的长度
}


4.10.3 在校验规则中添加分组

 //校验名称在1到30个字符
   //message提示校验出错所显示的校验信息
   @Size(min=1,max=30,message="{items.name.length.error}",groups={ValidGroup1.class})


4.10.4 在controller方法使用指定分组的校验

// value={ValidGroup1.class}指定使用ValidGroup1分组的 校验
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(Model model,HttpServletRequestrequest,Integer id,
@Validated(value={ValidGroup1.class}) ItemsCustomitemsCustom,BindingResult bindingResult)throws Exception



5 数据回显
5.1 什么数据回显
提交后,如果出现错误,将刚才提交的数据回显到刚才的提交页面。

5.2 pojo数据回显方法

1、springmvc默认对pojo数据进行回显。
pojo数据传入controller方法后,springmvc自动将pojo数据放到request域,key等于pojo类型(首字母小写)

使用@ModelAttribute指定pojo回显到页面在request中的key

2、@ModelAttribute还可以将方法的返回值传到页面

在商品查询列表页面,通过商品类型查询商品信息。
在controller中定义商品类型查询方法,最终将商品类型传到页面。



// 商品分类
//itemtypes表示最终将方法返回值放在request中的key
@ModelAttribute("itemtypes")
public Map《String, String》 getItemTypes() {

Map《String, String》 itemTypes = new HashMap《String,String》();
itemTypes.put("101", "数码");
itemTypes.put("102", "母婴");

return itemTypes;
}

页面上可以得到itemTypes数据。



商品类型:
《select name="itemtype"》
《option value="${itemtype.key }"》${itemtype.value}《/option》
《/select》




3、使用最简单方法使用model,可以不用@ModelAttribute

// 将错误信息传到页面
model.addAttribute("allErrors", allErrors);
//可以直接使用model将提交pojo回显到页面
model.addAttribute("items", itemsCustom);




5.3 简单类型数据回显

使用最简单方法使用model。

model.addAttribute("id", id);
0 0
原创粉丝点击