0
点赞
收藏
分享

微信扫一扫

Spring MVC - 高級參數綁定,服務端校驗,數據回線,異常處理


1.高级参数绑定

   1.1 包装类型pojo来接收查询条件参数
  分析:页面传参数的特点 :复杂,多样性;

           例如:

             (1) 客户信息包装类

 

package cn.labelnet.ssm.po;

/**
 * 客户信息包装类
 * @author yuan
 *
 */
public class FClientCustomVo {
	
	//别名
	private String uname;

	//客户信息
	private FClient client;

	public String getUname() {
		return uname;
	}

	public void setUname(String uname) {
		this.uname = uname;
	}

	public FClient getClient() {
		return client;
	}

	public void setClient(FClient client) {
		this.client = client;
	}
	

}


           (2)controller 


@RequestMapping(value = "/editClientIfofour")
	public String editClientIfofour(FClientCustomVo fcvo)  throws Exception{
		
		//业务开发
		
	
		return "/success.jsp";
	}


           (3)jsp

                    在这里可以发现 :客户姓名的 input标签name值为 包装类属性.属性 


<form method="post" action="${pageContext.request.contextPath}/clients/editClientIfofour.action" enctype="">
<!-- 
		<input type="file" value="上傳圖片 :" name=""><br>  -->
		
	客户姓名:	<input type="text"  name="client.username" /><br> <br> 
		
	别名 :	<input type="text"  name="uname"> <br> <br> 
		<input type="submit" value="提交">
          

	</form>


     1.2 数组绑定


  关键:将页面的多选操作,传数组操作


  规则:controller的方法参数定义为 数组 :Integer [] ids; 

name值一样为 controller的数组名;
	         <input type="checkbox"  name="ids" />



    1.3 list绑定
        需求:需要批量提交数据的时候,讲提交的数据绑定到List<pojo> 中
比如:成绩的录入,多门课程成绩提交
使用List接收页面提交的批量数据,通过pojo接收,在包装类pojo中,定义list<pojo>属性;
参数定义 :pojo属性 itemlist list;

                规则:

Spring MVC - 高級參數綁定,服務端校驗,數據回線,異常處理_数据校验

               实例:

               (1)list作为参数时,需要将其封装在包装类中使用


/**
 * 客户信息包装类
 * @author yuan
 *
 */
public class FClientCustomVo {
	
	//别名
	private String uname;

	//客户信息
	private FClient client;

	
	//list类型
	private List<FClient> clients;
	
	public List<FClient> getClients() {
		return clients;
	}

	public void setClients(List<FClient> clients) {
		this.clients = clients;
	}

	public String getUname() {
		return uname;
	}

	public void setUname(String uname) {
		this.uname = uname;
	}

	public FClient getClient() {
		return client;
	}

	public void setClient(FClient client) {
		this.client = client;
	}
	

}


        (2)controller :还是包装类


@RequestMapping(value = "/editClientIfofour")
	public String editClientIfofour(FClientCustomVo fcvo)  throws Exception{
		
		//业务开发
		
	
		return "/success.jsp";
	}


      (3)jsp页面中表单 的name值 规则为 :


<c:forEach items="${itemList}" var="item" varStaus="status" >
		      <input name=" list[${status.index}].name" value="" />
			  <input name=" list[${status.index}].age" value="" />
		  </c:forEach>


     1.4 map绑定

           (1)包装类实现


public classs QueryVo{
		   private Map<String,Object>  itemsinfo=new HashMap<String,Object>();
           //get、set
		   
		}


          (2)页面定义:


   

<input name="itemsinfo['name']" value="" />
		   <input name="itemsinfo['age']" value="" />


2.服务端校验

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

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

故,重视业务层的开发,校验比较多;


        2.2 springmvc校验开发

                  springmvc使用hibernate的校验框架validation,但和hibernate没有任何关系;

                  思路:
                  页面提交请求参数,请求到controller方法中,使用validation进行校验,如果校验出错,讲错误信息展示到页面;

                 示例 :需求:添加校验,比如注册日期是否为空的校验;   

                (1)导入 jar 包


                (2)配置校验器


<!-- 校验器 -->
	    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
	        
	        <!-- 配置hibernate校验器 -->
	        <property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
	        <!-- 指定校验使用的资源文件,在文件中配置校验错误信息,如过不指定默认使用classpath下的ValidationMessages.properties -->
            <property name="validationMessageSource" ref="messageSource"></property>
            	        
	    </bean>
	    
	    <!-- 校验错误信息配置文件-->
	    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
	        <!-- 资源文件名 -->
	        <property name="basenames">
	           <list>
	              <value>classpath:CustomValidationMessage</value>
	           </list>
	        </property> 
	        <!-- 资源文件编码格式 -->
	        <property name="fileEncodings" value="utf-8"></property>
	         <!-- 对资源文件内容缓存时间,单位秒 -->
	        <property name="cacheSeconds" value="120"></property>
	    </bean>


              

(3)注入到适配器中


<!-- 配置自定义参数映射 -->
		 <mvc:annotation-driven conversion-service="conversionService" validator="validator"></mvc:annotation-driven>



(4)添加pojo校验规则


public class FClient {

	 private Integer id;
	 //校验名称在1~30之间,message是提示的错误显示信息
	 @Size(min=1,max=30,message="{item.name.length.error}",groups={ValidatedGroup1.class})
	 private String username;
	 
	 private String client_certificate_no;
	 
	 @NotNull(message="{item.born_date.isNull}")
	 private Date born_date;
	 private String family_register_address;
}


(5)配置校验提示信息

                           CustomValidationMessage.properties 配置校验提示信息 :


item.name.length.error=\u59D3\u540D\u957F\u5EA6\u4E0D\u591F1~30
item.born_date.isNull=\u8BF7\u8F93\u5165\u4F60\u7684\u751F\u65E5


(6)捕获校验信息


  在需要校验的pojo前边添加@Validated,在需要校验的pojo后边添加BindingResult bindingResult接收出错信息;


  注意:@Validated和BindingResult bindingResult 是配对出现的,并且形参顺序固定的;


  

                         示例 :


/**
	 * 使用@ModelAtt
	 * @param m
	 * @param id
	 * @param fc
	 * @param binResult
	 * @return
	 * @throws Exception 
	 */
	
	@RequestMapping("editClientUpdateone")
	public String editClientUpdateone(Model m,Integer id,@ModelAttribute("custom") @Validated(value={ValidatedGroup1.class}) FClient fc ,BindingResult binResult)  throws Exception{

		int i=1/0;
		
		if(binResult.hasErrors()){
			List<ObjectError> errors = binResult.getAllErrors();
			for (ObjectError objectError : errors) {
				System.out.println(objectError.getDefaultMessage());
			}
			m.addAttribute("errorlist", errors);
			return "editClientIfo.action";
		}
		
		fc.setCreate_date(new Date());
			String result = fcService.updateClientIfo(id, fc);
			System.out.println(result);
		return "/success.jsp";
	}



(7)将错误信息传到页面上

                           使用Model参数实现 :


if(binResult.hasErrors()){
			List<ObjectError> errors = binResult.getAllErrors();
			for (ObjectError objectError : errors) {
				System.out.println(objectError.getDefaultMessage());
			}
			m.addAttribute("errorlist", errors);
			return "editClientIfo.action";
		}




(8)分组校验


           在pojo中定义校验规则,而pojo是被多个controller所共有,当不同的controller方法对同一个pojo进行校验,但是每个controller方法需要不同的校验;


  解决:定义多个校验分组,其实是一个java接口,分组中定义了那些规则;

                         定义一个接口 ,可以没有任何方法定义;

                         示例 :

                          validationGroup1接口 :


public interface ValidatedGroup1 {

	/**
	 * 校验分组 1
	 * 
	 */
	
}


                      设置分组 :


public String editClientUpdateone(Model m,Integer id,@ModelAttribute("custom") @Validated(value={ValidatedGroup1.class}) FClient fc ,BindingResult binResult)


                      pojo 设置分组 :


@Size(min=1,max=30,message="{item.name.length.error}",groups={ValidatedGroup1.class})
	 private String username;


3.数据回显


 什么是数据回显?

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

 pojo数据回显方法:

   (1)springmvc默认对pojo数据进行回显;

  pojo数据传入controller方法后,springmvc自动将pojo数据放到request域中,key等于pojo类型的首字母小写;



public String editClientUpdateone(Model m,Integer id,@ModelAttribute("custom") @Validated(value={ValidatedGroup1.class}) FClient fc ,BindingResult binResult)  throws Exception{



  


   (2)@ModelAttribute("") 还可以表示将方法的返回值放在request中的key中


    例如:


 

//将方法的返回值放在request中的key中
	@ModelAttribute("itemsType")
	public Map<String,String> getItemTypes(){
		Map<String,String> map=new HashMap<String, String>();
		map.put("101","黄金");
		map.put("102","白银");
		return map;
	}



注解的方法的返回值就可以获得到了,页面上就可以使用了;


 


   (3)最简单的回显方式


         不使用注解,使用model讲需要提交的pojo回显到页面;


model.addAttribute("");


         


简单类型的数据回显,只能使用model实现;


4.异常处理

                   预期异常:通过捕获
 运行时异常:通过测试,减少dao,service,controller的异常;

                             

Spring MVC - 高級參數綁定,服務端校驗,數據回線,異常處理_高级绑定_02


 dao,service,controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交给异常处理器进行异常处理;

 

 (1) 自定义异常类


package cn.labelnet.ssm.controller.exception;


/**
 * 自定义异常类
 * TODO
 * 作者:原明卓
 * 时间:2016年1月7日 下午4:36:10
 * 工程:SpringMvcMybatis1Demo
 */
public class CustomException extends Exception {
	
	private String msg;
	
	public CustomException(String msg) {
      super(msg);
      this.msg=msg;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}
	
}



  
  (2) 全局异常处理器
   思路:实现 HandlerExceptionResolver
解析出异常类型;
如果该异常类型是系统自定义的异常,直接取出异常信息并展示;
如果该异常类型不是自定义的异常,则构造一个自定义的异常类型信息;

package cn.labelnet.ssm.controller.exception;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

/**
 * 全局异常处理器
 * TODO
 * 作者:原明卓
 * 时间:2016年1月7日 下午4:40:18
 * 工程:SpringMvcMybatis1Demo
 */
public class CustomExceptionResover implements HandlerExceptionResolver {

	@Override
	public ModelAndView resolveException(HttpServletRequest arg0,
			HttpServletResponse arg1, Object arg2, Exception ex) {
//		解析出异常类型;
//		如果该异常类型是系统自定义的异常,直接取出异常信息并展示;
//		如果该异常类型不是自定义的异常,则构造一个自定义的异常类型信息;
		
		CustomException customException=null;
		if(ex instanceof CustomException){
			//是自定义异常类
			customException=(CustomException) ex;
		}else{
			customException=new CustomException("未知错误:"+ex.getMessage());
		}
		String msg=customException.getMsg();
		ModelAndView andView = new ModelAndView();
		andView.addObject("msg", msg);
		andView.setViewName("/error.jsp");
		return andView;
	}

}



 (3) SpringMvc 配置使用


    只要实现了HandlerExceptionResolver接口就是全局处理器,只需要配置class就可以了;


<!-- 配置全局异常处理类 -->
	    <bean class="cn.labelnet.ssm.controller.exception.CustomExceptionResover"></bean>



 ( 4)测试


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


与业务功能没有关系的异常,建议在controller中抛出异常;


举报
0 条评论