JAVAWEB开发之SpringMVC详解(二)——高级开发、数据回显、参数绑定集合、图片上传、json交互、validation校验、异常处理、RESTful支持、拦截器

这篇博客详细讲解了SpringMVC的高级开发技巧,包括数据回显的两种方法、参数绑定集合、商品图片上传的实现、JSON数据交互的配置和使用、Validation校验、统一异常处理以及RESTful支持。还介绍了拦截器的场景和应用,如用户认证拦截器的实现。
摘要由CSDN通过智能技术生成

知识回顾

springmvc框架
用户请求url到DispatcherServlet前端控制器,相当于中央调度器,降低系统各组件之间的耦合度。
DispatcherServlet前端控制器通过HandlerMapping处理器映射器根据url找到Handler。
DispatcherServlet前端控制器通过HandlerAdapter处理器适配器执行Handler。
DispatcherServlet前端控制器得到Handler返回的ModelAndView通过视图解析器ViewResolver进行视图解析。
视图解析:将程序中写的逻辑视图名,转成真正的视图(springmvc通过view表示各个类型不同的视图)。DispatcherServlet前端控制器调用View的渲染方法进行视图渲染(将ModelAndView中的model放到request域)

重点:SpringMVC的注解开发,企业中常用springmvc的注解开发
使用专门注解处理器映射器(RequestMappingHandlerMapping)和处理器适配器(RequestMappingHandlerAdapter)
注意:使用<mvc:annotation-driven/>可以替代上边的注解处理器映射器和注解处理器适配器的配置。
在Handler(controller)中定义很多的方法,一个方法通过@RequestMapping对url进行映射。
方法返回值:ModelAndView、String(jsp的逻辑视图名)、void(通过response将数据输出成json)。
方法输入参数(形参):springmvc需要将请求的key/value(串,id=001&id=002)、解析绑定到Handler(controller)中方法的形参上。
springmvc默认支持多类型的参数绑定。
默认支持的类型:HttpServletRequest、HttpServletResponse、HttpSession、Model(用于将数据填充到request域)。
@RequestParam注解:用于绑定单个请求参数,常用于简单类型参数(Integer、String、Float......)绑定。
不使用@ReuestParam要求请求参数的名称和方法形参名一致方可进行绑定。
对于简单类型参数中的日期型,建议使用自定义参数绑定,对日期类型数据个性化定义日期的格式。
自定义参数绑定:建议使用Converter进行参数绑定。
还可以绑定pojo、包装的pojo.

高级知识清单

注解开发:
  数据回显:表单提交错误,重新回到表单,用户重新填写数据,刚才提交的参数在页面上回显。
  集合类型(String[]、List<>、Map)的参数绑定
  springmvc上传图片(重点)
  json数据交互(提交json数据、响应json数据)(重点)
  Validation(springmvc使用校验方式: 使用Hibernate Validator(和Hibernate的ORM没有任何关系) )
拦截器(用于权限控制)

数据回显

需求  

表单提交出现错误,重新回到表单,用户重新填写数据,刚才提交的数据在页面上显示。

对简单类型的数据回显

对商品修改数据回显:
注意在进入修改页面的controller方法中和提交修改商品信息方法model.addAttribute方法设置key一致。

修改商品显示方法:
 @RequestMapping(value="/editItems",method={RequestMethod.GET}) 
	  public String editItems(Model model,Integer id) throws Exception{
	  
	 // 将id传递到页面
	  model.addAttribute("id",id);
		  
	  // 调用Service查询商品信息 
	  ItemsCustom itemsCustom = itemsService.findItemsById(id); //将模型数据传到jsp 
	  model.addAttribute("item",itemsCustom);
	  
	  //return "editItem_2";
	  return "editItem"; 
	  }
修改页面
<form id="itemForm" action="${pageContext.request.contextPath }/items/editItemSubmit.action" method="post" >
<input type="hidden" name="id" value="${id }"/>
修改商品信息:
<table width="100%" border=1>
<tr>
	<td>商品名称</td>
	<td><input type="text" name="name" value="${item.name }"/></td>
</tr>
 ......
修改商品提交方法
@RequestMapping("/editItemSubmit")
	public String editItemSubmit(Model model,Integer id, ItemsCustom itemsCustom) throws Exception {

		// 调用Service接口更新商品信息
		itemsService.updateItems(id, itemsCustom);

		// 进行数据回显
		model.addAttribute("id", id);
		
		// 提交后回到修改页面
		return "editItem";
	}
提交后查看网页源码

可以发现只有id回显到了修改页面
其过程原理是这样的:
第一次点击修改跳转到修改页面,从request域取值为name的id的属性赋值。
点击提交后将name的值(请求参数)提交到提交方法中为形参id赋值。
然后在提交方法内将id存入request域,再跳转到编辑页面,进行回显。

pojo数据类型回显

回显方法1:

使用model.addAttribute方法进行数据回显
@RequestMapping("/editItemSubmit")
	public String editItemSubmit(Model model,Integer id, ItemsCustom itemsCustom) throws Exception {

		// 调用Service接口更新商品信息
		itemsService.updateItems(id, itemsCustom);

		// 进行数据回显
		model.addAttribute("id", id);
		model.addAttribute("item",itemsCustom);
		
		// 提交后回到修改页面
		return "editItem";
}
过程就是:提交后表单数据传入到提交方法的形参id和itemsCustom中。
然后将形参存入到request域,属性命名保持与编辑页面取数据的名称一致。
跳转到编辑页面即可从request取值 进行回显。

回显方法2:

使用@ModelAttribute, 作用于将请求pojo数据放到Model中回显到页面
	public String editItemSubmit(Model model,Integer id, @ModelAttribute(value="item")ItemsCustom itemsCustom) throws Exception {
   
在@ModelAttribute方法指定的名称就是要填充到Model中的key,在页面上就要通过key取数据。

@ModelAttribute将方法返回值传到页面

需求:商品类别信息在商品信息页面展示
// 单独将商品类型的方法提出来,将方法返回值填充到request,在页面显示
	@ModelAttribute("itemsType")
	public Map<String, String> getItemsType() throws Exception{
		HashMap<String, String> itemsType = new HashMap<String, String>();
		itemsType.put("001", "数码");
		itemsType.put("002", "服装");
		return itemsType;
	}
页面
商品类别:
	<select> 
		<c:forEach items="${itemsType }" var="item">
			<option value="${item.key }">${item.value }</option>
		</c:forEach>
	</select>
使用@ModelAttribute将公用的取数据的方法返回值传递到页面,不用在controller的每一个方法中通过Model将数据传到页面。

参数绑定集合类型

绑定数组

需求:在商品查询列表页面,用户选择要删除的商品,批量删除商品。
在controller方法中如何将批量提交的数据绑定成数组类型。

页面定义

  <td><input type="checkbox" name="delete_id" value="${item.id }"/></td>

controller方法定义

// 删除商品
	@RequestMapping("/deleteItems")
	public String deleteItems(Integer[] delete_id) throws Exception{
		System.out.println(delete_id);
		return "success";
	}
运行结果:

绑定List<Object>

需求:批量修改商品信息提交
先进入批量修改商品页面,填写信息,点击提交

页面定义

<c:forEach items="${itemsList }" var="item" varStatus="s">
<tr>
	<td><input type="text" name="itemsList[${s.index }].name" value="${item.name }"/></td>
	<td><input type="text" name="itemsList[${s.index }].price" value="${item.price }"/></td>
	......
</tr>
注释:name值中的itemList
itemsList:controller方法形参包装类型中list的属性名
itemsList[0]或itemsList[0]......[]中是序号,从0开始
itemsList[index].name就是controller方法形参包装类型中list中pojo的属性名。

Controller方法定义

使用包装类型接收页面批量提交的数据,绑定成list
public class ItemsQueryVo {

	// 商品信息
	private ItemsCustom itemsCustom;

	// 定义一个List
	private List<ItemsCustom> itemsList;
        ......
}
使用包装类型作为形参 接收参数
// 批量修改商品提交
	@RequestMapping("/editItemsListSubmit")
    public String editItemsListSubmit(ItemsQueryVo itemsQueryVo){
		return "success";
	}

springmvc和struts的区别

SpringMVC是通过方法的形参接受参数,在使用时可以以单例方式使用,建议使用单例。
Struts是通过成员变量接收参数,在使用时必须以多例方式使用。

SpringMVC是基于方法开发,Struts是基于类开发。
SpringMVC将一个请求的Method和Handler进行关联绑定,一个method对应一个Handler。
SpringMVC开发是以方法为单位进行开发,方法更贴近Service(业务方法)。
经过实际测试,发现Struts标签解析速度比较慢,建议在实际开发中使用jstl。

商品图片上传

需求

在商品修改页面,增加图片上传的功能。
操作流程:
    用户进入商品修改页面
    上传图片
    点击提交(提交的是图片和商品的信息)
    再次进入修改页面,图片在商品修改页面展示

图片存储的问题

切记:不要将图片上传到工程目录,不方便进行工程维护。
实际电商项目中使用专门的图片服务器(比如Apache、Tomcat)
在Tomcat中进行虚拟目录的设置
设置方法如下:
在Tomcat下,找到conf文件下的server.xml,打开,在<Host>和</host>之间加上如下代码,然后就部署完成,重启服务器,浏  览器可以访问:
  <Context path="/虚拟目录名" docBase="目标目录位置" debug="0" reloadable="true" ></Context>
 虚拟目录名:浏览器访问的地址
 目标目录位置:项目所在目录的绝对路径

 reloadable="true" :服务器配置动态加载

测试:拖进目录中一张图片,启动服务器进行测试:


注意:图片目录中尽量进行目录分级存储,提高IO的访问速度。

配置图片上传解析器

springmvc使用commons-fileupload进行图片上传
commons-fileupload对应的springmvc的图片上传解析器:org.springframework.web.multipart.commons.CommonsMultipartResolver
在springmvc.xml中配置如下:
<!-- 文件上传 -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 设置上传文件的最大尺寸为5MB -->
		<property name="maxUploadSize">
			<value>5242880</value>
		</property>
	</bean>
加入commons-fileupload的jar包

编写上传图片的页面

表单属性的enctype要设置为multipart/form-data
<form id="itemForm" action="${pageContext.request.contextPath }/items/editItemSubmit.action" method="post" enctype="multipart/form-data">
添加图片上传组件<input type="file" name=""> 其中name的属性值要与控制器中接收图片的方法中的形参一致。
<td>商品图片</td>
	<td>
		<c:if test="${item.pic != null }">
			<img src="/pic/${item.pic}" width="100px" height="100px"/>
			<br/>
		</c:if>
		<input type="file" name="pictureFile"/>
	</td>

编写控制器方法

@RequestMapping("/editItemSubmit")
	// public String editItemSubmit(Integer id,ItemsCustom
	// itemsCustom,ItemsQueryVo itemsQueryVo) throws Exception{
	public String editItemSubmit(Model model,Integer id, 
			@ModelAttribute(value="item")ItemsCustom itemsCustom,
			// 上传图片
			MultipartFile pictureFile
			) throws Exception {
		// 进行数据回显
		model.addAttribute("id", id);
		//model.addAttribute("item",itemsCustom);
		
		//进行图片上传
		if (pictureFile!=null && pictureFile.getOriginalFilename()!=null && pictureFile.getOriginalFilename().trim().length()>0) {
			// 图片上传成功后,将图片的地址写到数据库
			String filePath = "/Users/liuxun/Desktop/pictures";
			// 上传文件原始名称
			String originFileName = pictureFile.getOriginalFilename();
			// 新的图片的名称
			String newFileName = UUID.randomUUID()+originFileName.substring(originFileName.lastIndexOf("."));
			// 新文件
			File file = new File(filePath+File.separator+newFileName);
			
			// 将内存中的文件写入磁盘
			pictureFile.transferTo(file);
			
			// 图片上传成功,将图片地址写入数据库
			itemsCustom.setPic(newFileName);
		}
		
		// 调用Service接口更新商品信息
		itemsService.updateItems(id, itemsCustom);
		
		// 提交后回到修改页面
		return "editItem";
		// 请求重定向
		//return "redirect:queryItems.action";
		// 转发
		// return "forward:queryItems.action";
	}
提交后页面效果如下


json数据交互

需求

json数据格式是比较简单和容易理解的,json数据格式常用于远程接口传输,http传输json数据,非常方便页面进行 提交/请求结果解析,对json数据的解析。

SpringMVC解析json加入json解析包

springmvc默认采用MappingJacksonHttpMessageConverter对json数据进行转换,需要加入jackson的包如下所示:

在处理器适配器中注入MappingJacksonHttpMessageConverter

让处理器适配器支持json数据解析,需要注入MappingJacksonHttpMessageConverter
 <!-- 注解适配器 -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    	<!-- 在webBindingInitializer中注入自定义属性编辑器,自定义转换器 -->
    	<property name="webBindingInitializer" ref="customBinder"/>
    	<!-- 加入json数据的消息转换器 MappingJacksonHttpMessageConverter依赖的Jackson包 -->
    	<property name="messageConverters">
    		<list>
    			<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
    		</list>
    	</property>
    </bean>
需要将支持json数据解析
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值