Springmvc学习笔记(三)

16 springmvc校验

16.1 校验理解

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

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

16.2 springmvc校验需求

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

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

16.3 环境准备

hibernate的校验框架validation所需要jar包:
在这里插入图片描述

16.4 配置校验器

在springmvc.xml配置文件中配置:

<!-- 校验器 -->  
<bean id="validator"  
    class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">  
    <!-- 校验器-->  
    <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>

之后在工程的源文件夹config下创建CustomValidationMessages.properties配置文件,用来配置校验错误信息。

16.5 校验器注入到处理器适配器

<mvc:annotation-driven conversion-service="conversionService"
	validator="validator"></mvc:annotation-driven>

16.6 在pojo中添加校验规则

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

public class Items {
    private Integer id;
    //校验名称在1-30个字符之内
    @Size(min=1,max=30,message="{items.name.length.error}")
    private String name;
    //商品生产日期不能为空
    @NotNull(message="{items.createtime.isNull}")
    private Date ceatime;

16.7 CustomValidationMessages.properties

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

#添加校验错误提示信息
items.name.length.error=请输入1-30个字符的商品名称
items.createtime.isNull=请输入商品生产日期

16.8 捕获校验错误信息(@Validated与BindingResult)

//商品修改提交
//在需要校验的pojo前边加@Validated,在需要校验的pojo后边添加BindingResult bindingResult接收校验出错信息  
//注意:@Validatedh和BindingResult bindingResult是配对出现,并且在形参中出现的顺序是固定的(一前一后)
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(HttpServletRequest request,Integer id,
		@Validated ItemsCustom itemsCustom,BindingResult bindingResult) throws Exception {
	//校验错误信息
	if(bindingResult.hasErrors()) {
		//输出错误信息
		List<ObjectError> allErrors = bindingResult.getAllErrors();
		
		for (ObjectError objectError : allErrors) {
			System.out.println(objectError.getDefaultMessage());
		}
	}
	itemsService.update(id, itemsCustom);
	//重定向到商品的查询列表  
    return "redirect:queryItems.action";
}

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

在controller中将错误信息传到页面即可。

//获取校验错误信息  
if(bindingResult.hasErrors()){  
    //输出错误信息  
    List<ObjectError> allErrors=bindingResult.getAllErrors();  
      
    for(ObjectError objectError:allErrors){  
        //输出错误信息  
        System.out.println(objectError.getDefaultMessage());  
    }  
      
    //将错误传到页面  
    model.addAttribute("allErrors",allErrors);  
    //出错之后要跳转的页面  
    return "items/editItems";  
}

页面显示错误信息:
在商品编辑页面editItems.jsp中显示错误信息:

<!-- 显示错误信息 -->  
<c:if test="${allErrors!=null}">   
    <c:forEach items="${allErrors}" var="error">  
        <font color="red">${error.defaultMessage}</font><br/>  
    </c:forEach>  
</c:if>

16.10 分组校验

16.10.1 需求

上一次我们学习了validation校验的配置和使用方法,我们不难发现会有一些问题:
在pojo中定义校验规则,而pojo是被多个controller所共用,当不同的controller方法对同一个pojo进行校验,但是每个controller方法需要不同的校验。

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

16.10.2 校验分组

我们在工程中新建一个包cn.edu.hpu.ssm.controller.validation,并在包中创建两个校验分组接口;

  • 其中ValidGroup1.java:

    public interface ValidGroup1 {
    	//此接口不需要定义任何方法,仅是对不同校验规则进行分组
    	//此分组只校验商品名称长度
    }
    
  • ValidGroup2.java:

    public interface ValidGroup2 {  
    	//接口中不需要定义任何方法,仅是对不同的校验规则进行分组  
        //其它  
    }
    
16.10.3 在校验规则中添加分组
public class Items {
    private Integer id;

    //校验名称在1-30个字符之内
    //groups:用来标识此校验属于哪个分组,groups可以定义多个分组 
    @Size(min=1,max=30,message="{items.name.length.error}",groups={ValidGroup1.class})
    private String name;
16.10.4 在controller方法使用指定分组的校验
//商品信息修改提交  
//在需要校验的pojo前边加@Validated,在需要校验的pojo后边添加BindingResult bindingResult接收校验出错信息  
//注意:@Validatedh和BindingResult bindingResult是配对出现,并且在形参中出现的顺序是固定的(一前一后)  
//value={ValidGroup1.class}指定使用ValidGroup1分组的校验  
@RequestMapping("/editItemsSubmit")  
public String editItemsSubmit(Model model,
							  HttpServletRequest request,Integer id,  
        					  @Validated(value={ValidGroup1.class}) ItemsCustom itemsCustom,
							  BindingResult bindingResult)throws Exception{  
//代码省略  
}

17 数据回显

17.1 什么是数据回显

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

17.2 pojo数据回显方法

17.2.1 springmvc默认对pojo数据进行回显。

pojo数据传入controller方法后,springmvc自动将pojo数据放到request域,key等于pojo类型(首字母小写)
说白了就是items类

items类在网页中取name的写法是: i t e m s . n a m e , 也 就 是 r e q u e s t 域 的 k e y 是 i t e m s , 也 就 是 当 初 c o n t r o l l e r 方 法 中 包 装 进 去 的 v a l u e 的 k e y ( m o d e l . a d d A t t r i b u t e ( " i t e m s " , i t e m s ) ; ) , 如 果 在 网 页 中 改 为 {items.name},也就是request域的key是items,也就是当初controller方法中包装进去的value的key(model.addAttribute("items",items);),如果在网页中改为 items.namerequestkeyitemscontrollervaluekey(model.addAttribute("items",items);){items22.name}就取不出来值了,因为key不对了,当然也就无法使用springmvc的默认回显方法了。

为了防止这种错误或者是为了让回显数据配置更加轻松,我们可以使用@ModelAttribute指定pojo回显到页面在request中的key

如:(现在我们把当初controller方法中包装进去的value的key改为items22(model.addAttribute(“items22”,items)😉,此时如果不用@ModelAttribute注解,springmvc默认的回显机制会默认从request域中寻找key为items(pojo类首字母小写)的value,结果就是找不到。已经经过验证)

//商品信息修改提交  
//在需要校验的pojo前边加@Validated,在需要校验的pojo后边添加BindingResult bindingResult接收校验出错信息  
//注意:@Validatedh和BindingResult bindingResult是配对出现,并且在形参中出现的顺序是固定的(一前一后)  
//value={ValidGroup1.class}指定使用ValidGroup1分组的校验  
//@ModelAttribute可以指定pojo回显到页面在request中的key  
@RequestMapping("/editItemsSubmit")  
public String editItemsSubmit(Model model,
					HttpServletRequest request,
					Integer id,  
					@ModelAttribute("items22") @Validated(value={ValidGroup1.class}) ItemsCustom itemsCustom,
					BindingResult bindingResult)throws Exception{  
//具体修改方法略  
}

修改页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"  
	pageEncoding="UTF-8"%>  
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt"%>  
<!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>修改商品信息</title>  
 
</head>  
<body> 
    <!-- 显示错误信息 -->  
    <c:if test="${allErrors!=null}">  
        <c:forEach items="${allErrors}" var="error">  
	        <font color="red">${error.defaultMessage}</font><br/>  
	    </c:forEach>  
	</c:if>  


	<form id="itemForm" action="${pageContext.request.contextPath 	}/items/editItemsSubmit.action" method="post" >  
	<input type="hidden" name="id" value="${items22.id }"/>  
	修改商品信息:  
	<table width="100%" border=1>  
	<tr>  
	    <td>商品名称</td>  
	    <td><input type="text" name="name" value="${items22.name }"/></td>  
	</tr>  
	<tr>  
	    <td>商品价格</td>  
	    <td><input type="text" name="price" value="${items22.price }"/></td>  
	</tr>  
	<tr>  
	    <td>商品生产日期</td>  
	    <td><input type="text" name="createtime" value="<fmt:formatDate value="${items22.createtime}" 
            pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>  
	</tr>  
	<%-- <tr>  
	    <td>商品图片</td>  
	    <td>  
	        <c:if test="${item.pic !=null}">  
	            <img src="/pic/${item.pic}" width=100 height=100/>  
	            <br/>  
	        </c:if>  
	        <input type="file"  name="pictureFile"/>   
	    </td>  
	</tr> --%>  
	<tr>  
	    <td>商品简介</td>  
	    <td>  
	    <textarea rows="3" cols="30" name="detail">${items22.detail }</textarea>  
	    </td>  
	</tr>  
	<tr>  
	<td colspan="2" align="center"><input type="submit" value="提交"/>  
	</td>  
	</tr>  
	</table>  
    </form>
    </body>
</html>
17.2.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数据(不需要URL请求)。
商品类型:

<select name="itemtype">  
    <c:forEach items="${itemtypes}" var="itemtype">  
        <option value="${itemtype.key}">${itemtype.value }</option>  
    </c:forEach>  
</select>
17.2.3 使用最简单方法使用model,可以不用@ModelAttribute
@RequestMapping("/editItemsSubmit")  
public String editItemsSubmit(Model model,HttpServletRequest request,Integer id,
  @Validated(value={ValidGroup1.class}) ItemsCustom itemsCustom,BindingResult bindingResult)
  throws Exception{  
    //获取校验错误信息  
    if(bindingResult.hasErrors()){  
        //输出错误信息  
        List<ObjectError> allErrors=bindingResult.getAllErrors();  
        for(ObjectError objectError:allErrors){  
            //输出错误信息  
            System.out.println(objectError.getDefaultMessage());  
        }  
        //将错误传到页面  
        model.addAttribute("allErrors",allErrors);  
        //可以直接使用model将提交pojo回显到页面  
        model.addAttribute("items22",itemsCustom);  
        //出错之后要跳转的页面  
        return "items/editItems";  
    }  
    //调用service更新商品信息,页面需要将商品信息传到此方法  
    itemsService.updateItems(id, itemsCustom);  
    //重定向到商品的查询列表  
    return "redirect:queryItems.action";  
}

17.3 简单类型数据回显

使用最简单方法使用model。
还是使用model或者request去封装跳转即可
model.addAttribute("id",id);

18 异常处理

18.1 异常处理思路

系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:
在这里插入图片描述
springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。

18.2 自定义异常类

对不同的异常类型定义异常类,继承Exception。

public class CustomException extends Exception {
	private String message;
	public CustomException(String message) {
		super(message);
		this.message = message;
	}
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
}

18.3 全局异常处理器

  • 思路:

    • 系统遇到异常,在程序中手动抛出,dao抛给service、service给controller、controller抛给前端控制器,前端控制器调用全局异常处理器。
  • 全局异常处理器处理思路:

    • 解析出异常类型。
    • 如果该异常类型是系统自定义的异常,直接取出异常信息,在错误页面展示。
    • 如果该异常类型不是系统自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)。
  • springmvc提供一个HandlerExceptionResolver接口

    public class CustomExceptionResolver implements HandlerExceptionResolver {
        //系统抛出异常
        @Override
        public ModelAndView resolveException(HttpServletRequest request,
                                             HttpServletResponse response, 
                                             Object handler, Exception ex) {
            //handler就是处理器适配器要执行的Handler对象(只有method)
            //解析出异常类型。
            //如果该 异常类型是系统 自定义的异常,直接取出异常信息,在错误页面展示。
            CustomException customException = null;
            if(ex instanceof CustomException) {
                customException = (CustomException)ex;
            } else {
                //如果该 异常类型不是系统 自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)。
                customException = new CustomException("未知错误");
            }
            String message = customException.getMessage();
            ModelAndView modelAndView = new ModelAndView();
            //将错误信息传送到页面
            modelAndView.addObject("message", message);
            //指向到错误界面
            modelAndView.setViewName("error");
            return modelAndView;
        }
    }
    

18.4 错误页面

在WEB-INF/jsp文件夹下创建error.jsp页面,内容为:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  
<%  
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>error</title>  
  </head>  
  <body>  
    ${message } <br>  
  </body>  
</html>

18.5 在springmvc.xml配置全局异常处理器

<!--
	全局异常处理器
	只要你实现了HandlerExceptionResolver接口,这个
	类就是一个全局异常处理器
-->
<bean class="cn.itcast.ssm.exception.CustomExceptionResolver" />

18.6 异常测试

在controller、service、dao中任意一处需要手动抛出异常。
如果是程序中手动抛出的异常,在错误页面中显示自定义的异常信息,如果不是手动抛出异常说明是一个运行时异常,在错误页面只显示“未知错误”。
在商品修改的controller方法中抛出异常。

@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})  
//@RequestParam里面指定reuqest传入参数和形参进行绑定。  
//通过required属性指定参数是否必须要传入  
//通过defaultValue可以设置默认值,如果id参数没有传入,将默认值和形参绑定  
public String editItems(Model model,
  @RequestParam(value="id",required=true,defaultValue="") Integer items_id)throws Exception{  
    //调用service根据商品id查询商品信息  
    ItemsCustom itemsCustom=itemsService.findItemsById(items_id);  
    //判断商品是否为空,根据id没有查到商品,提示用户商品信息并不存在  
    if(itemsCustom==null){  
        throw new CustomException("商品的修改信息不存在!");  
    }  
    //通过形参中的model将model数据传到页面  
    //相当于modelAndView.addObject方法  
    model.addAttribute("items22",itemsCustom);  
    return "items/editItems";  
}

其中上面用到的service方法:

@Override  
public ItemsCustom findItemsById(Integer id) throws Exception {  
    Items items=itemsMapper.selectByPrimaryKey(id);  
    //中间对商品信息进行业务处理  
    //...  
    //最终返回ItemsCustom  
    ItemsCustom itemsCustom=null;  
    //将item的内容拷贝到itemsCustom  
    if(items!=null){  
        itemsCustom=new ItemsCustom();  
        BeanUtils.copyProperties(items, itemsCustom);  
    }  
    return itemsCustom;  
}

同样在Service中也可以抛出异常

如果与业务功能相关的异常,建议在service中抛出异常。
与业务功能没有关系的异常,建议在controller中抛出。

上边的功能,建议在service中抛出异常。

19 上传图片

19.1 需求

在修改商品页面,添加上传商品图片功能。

19.2 springmvc中对多部件类型解析

在页面form中提交enctype="multipart/form-data"的数据时,需要springmvc对multipart类型的数据进行解析。
在springmvc.xml中配置multipart类型解析器。

<!-- 文件上传 -->  
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
    <!-- 设置上传文件的最大尺寸为5MB -->  
    <property name="maxUploadSize">  
        <value>5242880</value>  
    </property>  
</bean>

注:在电商企业开发的时候,是需要单独建立图片服务器的,这里我们仅仅在tomcat服务器的本工厂下使用一个文件夹来存放图片

19.3 加入上传图片的jar

上边的解析内部使用下边的jar进行图片上传。
在这里插入图片描述

19.4 创建图片虚拟 目录 存储图片

  • 通过图形界面配置:

在这里插入图片描述
在这里插入图片描述

  • 也可以直接修改tomcat的配置:
    在conf/server.xml文件,添加虚拟目录(注意是在最下方的Host标签对中添加):

    <Context docBase="D:\JAVA\temp" path="/pic" reloadable="false"/>  
    

测试:我们在D:\JAVA\temp下放置一个名为yuanchuanggongzuoshi.png的图片,重启服务器后直接访问http://localhost:8080/pic/yuanchuanggongzuoshi.png路径就可以直接看到图片,所以我们的配置是成功的。(以后我们上传数据往物理路径D:\JAVA\temp下去上传,查看图片往/pic下去查)

注意:在图片虚拟目录 中,一定将图片目录分级创建(提高i/o性能),一般我们采用按日期(年、月、日)进行分级创建。

19.5 上传图片代码

19.5.1 页面
<tr>  
    <td>商品图片</td>  
    <td>  
        <c:if test="${items22.pic !=null}">  
            <img src="/pic/${items22.pic }" width=100 height=100/>  
            <br/>  
        </c:if>  
        <input type="file"  name="items_pic"/>   
    </td>  
</tr> 

注意:"/pic"路径是绝对路径,不要加${pageContext.request.contextPath }/…

19.5.2 controller方法

修改:商品修改controller方法:

//商品修改提交
//@ModelAttribute可以指定pojo回显到页面在request中的key
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(Model model,
		HttpServletRequest request,
		Integer id,
		@Validated(value={ValidGroup1.class}) ItemsCustom itemsCustom,
		BindingResult bindingResult,
		MultipartFile items_pic//接收商品图片
		) throws Exception {
	
	//校验错误信息
	if(bindingResult.hasErrors()) {
		//输出错误信息
		List<ObjectError> allErrors = bindingResult.getAllErrors();
		
		for (ObjectError objectError : allErrors) {
			System.out.println(objectError.getDefaultMessage());
		}
		
		//将错误传到页面  
	    model.addAttribute("allErrors",allErrors);
	    
	    //可以直接使用model将提交pojo回显到页面  
	    model.addAttribute("items22", itemsCustom);
	    
	    //出错之后要跳转的页面  
	    return "items/editItems";  
	}
	
	//上传图片原始名称
	String originalFileName = items_pic.getOriginalFilename();
	
	//上传图片
	if(items_pic != null && originalFileName != "" && originalFileName.length() > 0) {
		
		//存储图片的物理路径
		String pic_path = "D:\\JAVA\\temp\\";
		
		//新图片名称
		String newFileName = UUID.randomUUID()
				+originalFileName.substring(originalFileName.lastIndexOf("."));
		
		File newfile = new File(pic_path+newFileName);
		
		//将内存中的数据写入磁盘
		items_pic.transferTo(newfile);
		
		//将新的图片名写到itemsCustom
		itemsCustom.setPic(newFileName);
	}
	
	itemsService.update(id, itemsCustom);
	
	//重定向到商品的查询列表  
    return "redirect:queryItems.action";
}

19.6 缺陷

问题:
编辑时如果不修改图片,直接提交的时候图片就没了。原因是,图片所在的type=file的input标签中没有value,当提交form表单的时候会将空值提交上去,在数据库存储阶段,如果你没有判断items_pic的空,空的图片路径,就会覆盖数据库原有的图片路径。
解决这个问题的方法就是,在存储图片相关信息时,判断前端传来的图片值是否为空,如果为空则不要update该字段。

20 json数据交互

20.1 为什么要进行json数据交互

json数据格式在接口调用中、html页面中较常用,json格式比较简单,解析还比较方便。
比如:webservice接口,传输json数据.

20.2 springmvc进行json交互

在这里插入图片描述

  1. 请求json、输出json,要求请求的是json串,所以在前端页面中需要将请求的内容转成json,不太方便。
  2. 请求key/value、输出json。此方法比较常用。

20.3 环境准备

20.3.1 加载json转的jar包
  • springmvc中使用jackson的包进行json转换(@requestBody和@responseBody使用下边的包进行json转),如下:
    jackson-core-asl-1.9.11.jar
    jackson-mapper-asl-1.9.11.jar

  • @RequestBody作用:
    @RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。

  • 本例子应用:
    @RequestBody注解实现接收http请求的json数据,将json数据转换为java对象

  • @ResponseBody作用:
    该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如: json,xml等,通过Response响应给客户端

  • 本例子应用:
    @ResponseBody注解实现将controller方法返回对象转换为json响应给客户端

20.3.2 3.2配置json转换器

在注解适配器中加入messageConverters

<!--注解适配器 -->  
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">  
    <property name="messageConverters">  
    <list>  
    <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>  
    </list>  
    </property>  
</bean> 

注意:如果使用<mvc:annotation-driven /> 则不用定义上边的内容。

20.4 json交互测试

20.4.1 输入json串,输出是json串
20.4.1.1 jsp页面

使用jquery的ajax提交json串,对输出的json结果进行解析。
使用jduery别忘记引入jquery-1.4.4.min.js

<%@ page language="java" contentType="text/html; charset=UTF-8"
    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>json交互测试</title>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript">
//请求为json,响应为json
function requestJson(){
	$.ajax({
		type:'post',
		url:'${pageContext.request.contextPath }/requestJson.action',
		contentType:'application/json;charset=utf-8',
		//数据格式是json串,商品信息
		data:'{"name":"手机","price":"100"}',
		success:function(data){//返回json结果
			alert(data);
		}
	});
}
</script>
</head>
<body>
<input type="button" οnclick="requestJson()" value="请求的是json,输出的是json"/>
</body>
</html>
20.4.1.2 controller
//json交互测试  
@Controller  
public class JsonText {  
    //请求json(商品信息),输出json(商品信息)  
    //@RequestBody将请求的商品信息的json串转成itemsCustom对象  
    //@ResponseBody将itemsCustom转成json格式输出  
    @RequestMapping("/requestJson")  
    public @ResponseBody ItemsCustom requestJson(@RequestBody ItemsCustom itemsCustom){  
        //@ResponseBody将itemsCustom转成json格式输出  
        return itemsCustom;  
    }  
}
20.4.1.3 测试结果
20.4.2 输入key/value,输出是json串
20.4.2.1 jsp页面
使用jquery的ajax提交key/value串,对输出的json结果进行解析。  
<%@ page language="java" contentType="text/html; charset=UTF-8"
    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>json交互测试</title>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript">
//请求为key/value,响应为json
function responseJson(){
	$.ajax({
		type:'post',
		url:'${pageContext.request.contextPath }/responseJson.action',
		//请求的是key/value,这里不需要指定contentType,因为默认就是key/value类型  
		//contentType:'application/json;charset=utf-8', 
		//数据格式是json串,商品信息
		data:'{"name":"手机","price":"100"}',
		success:function(data){//返回json结果
			alert(data);
		}
	});
}
</script>
</head>
<body>
<input type="button" οnclick="responseJson()" value="请求的是key/value,输出的是json"/>
</body>
</html>
20.4.2.2 controller
//json交互测试  
@Controller  
public class JsonText {  
      
    //请求key/value(商品信息),输出json(商品信息)  
    @RequestMapping("/responseJson")  
    public @ResponseBody ItemsCustom responseJson(ItemsCustom itemsCustom){  
          
        //@ResponseBody将itemsCustom转成json格式输出  
        System.out.println("前台传过来得商品名:"+itemsCustom.getName());  
        return itemsCustom;  
    }  
}
20.4.2.3 测试

后台控制台输出了"前台传过来的商品名:手机",且查看http数据可以看到json数据的反馈。

21 springmvc对RESTful支持

21.1 什么是RESTful

RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。

RESTful-表现层状态转换(即Representational State Transfer的缩写)其实是一个开发理念,是对http的很好的诠释。

(1)对url进行规范,写RESTful格式的url

非REST的url:http://…/queryItems.action?id=001&type=T01
REST的url风格:http://…/items/001
特点:url简洁,将参数通过url传到服务端
(2)http的方法规范
不管是删除、添加、更新。。使用url是一致的,如果进行删除,需要设置http的方法为delete,同理添加。。。

后台controller方法:判断http方法,如果是delete执行删除,如果是post执行添加。

(3)对http的contentType规范
请求时指定contentType,要json数据,设置成json格式的type。。

21.2 REST的例子

21.2.1 需求

查询商品信息,返回json数据。

21.2.2 controller

定义方法,进行url映射使用REST风格的url,将查询商品信息的id传入controller .
输出json使用@ResponseBody将java对象输出json。

//查询商品信息,输出json  
///itemsView/{id}里面的{id}表示将这个位置的参数传到@PathVariable指定名称中  
@RequestMapping("/itemsView/{id}")  
public @ResponseBody ItemsCustom itemsView(@PathVariable("id") Integer id)throws Exception{  
    //调用service查询商品信息  
    ItemsCustom itemsCustom=itemsService.findItemsById(id);  
          
    return itemsCustom;  
}

@RequestMapping(value="/ itemsView/{id}"):{xxx}占位符,请求的URL可以是“/viewItems/1”或“/viewItems/2”,通过在方法中使用@PathVariable获取{xxx}中的xxx变量。
@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。
如果RequestMapping中表示为"/ itemsView /{id}",id和形参名称一致,@PathVariable不用指定名称。

21.2.3 REST方法的前端控制器配置

在web.xml配置:

<!-- SpringMvc前端控制器,rest配置 -->  
<servlet>  
    <servlet-name>springmvc_rest</servlet-name>  
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
    <init-param>  
        <param-name>contextConfigLocation</param-name>  
        <param-value>classpath:spring/springmvc.xml</param-value>  
    </init-param>  
</servlet>  
  
<servlet-mapping>  
    <servlet-name>springmvc_rest</servlet-name>  
    <url-pattern>/</url-pattern>  
</servlet-mapping>

21.3 对静态资源的解析

配置前端控制器的url-parttern中指定/,对静态资源的解析出现问题:
在这里插入图片描述
在springmvc.xml中添加静态资源解析方法。

<!-- 静态资源的解析
	包括:js/css/img... -->
<resources location="/js/" mapping="/js/**" />
<resources location="/img/" mapping="/img/**" />
<resources location="/css/" mapping="/css/**" />

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值