文档章节

SpringMVC+Spring+Mybatis整合应用(2)

江左煤郎
 江左煤郎
发布于 2018/12/02 16:45
字数 3217
阅读 28
收藏 2

1. 包装类型pojo对象中pojo属性参数绑定

   1. 对于属性都是简单类型的pojo类

    如果需要将请求中的参数绑定到该pojo对象形参中,只需要保证请求中携带的key/value格式的参数中的key值与pojo类中的属性名相同即可,SpringMVC会自动将请求中的参数绑定或者说注入到pojo对象的属性中,比如

    <form action="user/regist.do">
    	<div>请输入名称:<input type="text" name="userName"></div>
    	<div>请输入密码:<input type="password" name="userPassword"></div>
    	<div>请输入年龄:<input type="text" name="userAge"></div>
    	<div>请输入地址:<input type="text" name="userAddress"></div>
    	<div>请输入手机:<input type="text" name="userTelephone"></div>
    	<div><input type="submit" value="注册"></div>
    </form>
public class User {
    private Integer userAccount;
    private String userName;
    private String userPassword;
    private Integer userAge;
    private String userAddress;
    private String userTelephone;
//省略每个属性的get/set方法
}
@Controller
@RequestMapping("/user")
public class UserController {

	@RequestMapping("/regist")
	public String userRegist(User user){
		return "login";
	}
	
}

    2. 如果形参是一个pojo类,而且该pojo类中的某个属性也是一个pojo类

    同样以上面的注册为例

public class UserVo {
	private User user;
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
}

@Controller
@RequestMapping("/user")
public class UserController {

	@RequestMapping("/regist")
	public String userRegist(UserVo user){
		return "login";
	}
	
}
    <form action="user/regist.do">
    	<div>请输入名称:<input type="text" name="user.userName"></div>
    	<div>请输入密码:<input type="password" name="user.userPassword"></div>
    	<div>请输入年龄:<input type="text" name="user.userAge"></div>
    	<div>请输入地址:<input type="text" name="user.userAddress"></div>
    	<div>请输入手机:<input type="text" name="user.userTelephone"></div>
    	<div><input type="submit" value="注册"></div>
    </form>

可以看出,只需要保证请求参数的key值为绑定的目标pojo对象中的 属性名.属性名.属性名···即可

2. 集合类型参数绑定

    1. 如果要绑定的controller方法的形参是一个数组:

  • 在Jsp页面中的写法
        <form action="">
        	<input type="checkbox" name="arr" value="1">
            <input type="checkbox" name="arr" value="2">
            <input type="checkbox" name="arr" value="3">
        	<!-- 多个checkbox,name属性的值相同 -->
        </form>

     

  • 在controller方法中的形参

    	@RequestMapping("uri")
    	public String toPage(int[] arr){
    		return "";
    	}

    和简单类型参数绑定类似,保证请求中的key/value数据的key值与形参名相同即可

    2. 如果绑定List类型的参数:

  • 在controller方法中的形参
    //绑定的pojo类型
    public class User {
        private Integer userAccount;
        private String userName;
        private String userPassword;
        private Integer userAge;
        private String userAddress;
        private String userTelephone;
    //省略get/set方法
    }
    public class UserVo {
    	//将请求中参数对应的pojo集合放在另一个包装类中作为属性
    	private List<User> users;
    	public List<User> getUsers() {
    		return users;
    	}
    	public void setUsers(List<User> users) {
    		this.users = users;
    	}
    }
    //controller方法的形参
    	@RequestMapping("uri")
    	public String test(UserVo uservo){
    		return page;
    	}

    使用List接收页面提交的批量数据会被绑定为list<pojo>类型的数据,但不能直接通过list<pojo>形参进行接收,而是通过另一个包装pojo接收,在包装pojo中定义list<pojo>属性

  • 在jsp页面中的写法:name属性值的写法应为包装pojo中 list<pojo>类型属性的属性名[下标(从0开始)].属性名.属性名···
        <form action="">
        	<div>
        		<input type="text" name="users[0].userAccount" value="">
        		<input type="text" name="users[0].userName" value="">
        		<input type="text" name="users[0].userPassword" value="">
        		<input type="text" name="users[0].userAge" value=""> 
        		<input type="text" name="users[0].userAddress" value="">
        		<input type="text" name="users[0].userTelephone" value="">
        	</div>
        	<div>
        		<input type="text" name="users[1].userAccount" value="">
        		<input type="text" name="users[1].userName" value="">
        		<input type="text" name="users[1].userPassword" value="">
        		<input type="text" name="users[1].userAge" value=""> 
        		<input type="text" name="users[1].userAddress" value="">
        		<input type="text" name="users[1].userTelephone" value="">
        	</div>
        	<div>
        		<input type="text" name="users[2].userAccount" value="">
        		<input type="text" name="users[2].userName" value="">
        		<input type="text" name="users[2].userPassword" value="">
        		<input type="text" name="users[2].userAge" value=""> 
        		<input type="text" name="users[2].userAddress" value="">
        		<input type="text" name="users[2].userTelephone" value="">
        	</div>
        </form>

     

3. 服务端数据校验

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

    2. 服务端校验:

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

    3. 简单开发应用:SpringMVC主要使用Hibernate的校验框架(和hibernate没有任何关系)。校验思路就是页面提交请求的参数,请求到controller方法中,使用validation进行校验。如果校验出错,将错误信息展示到页面。

  • 准备环境:导入相关jar包,
  • 修改SpringMVC的配置文件,将校验器配置到处理器适配器中
    	<mvc:annotation-driven validator="validator"></mvc:annotation-driven>
    	<!-- 配置校验器 -->
    	<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    		<!-- 配置第三方提供的校验器类 :Hibernate校验器类-->
    		<property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
    		<!-- 指定校验使用的资源文件,在文件中配置校验错误信息文件源 -->
    		<property name="validationMessageSource" ref="messageSource"></property>
    	</bean>
    	<!-- 配置校验信息错误文件源,可以配置多个 -->
    	<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    		<property name="basenames">
    			<list>
    				<!-- 会自动解析为当前类路径下,名为validationMessage1.properties的文件 -->
    				<value>classpath:validationMessage1</value>
    			</list>
    		</property>
    		<!-- 指定解析文件的编码格式 -->
    		<property name="fileEncodings" value="utf-8"></property>
    		<!-- 指定对资源文件内容的缓存时间,单位为秒 -->
    		<property name="cacheSeconds" value="120"></property>
    	</bean>

     

  • 在pojo类中添加校验规则
    package user_manage.pojo;
    
    import javax.validation.constraints.NotNull;
    import javax.validation.constraints.Size;
    public class User {
        //验证正则表达式,regexp写正则表达式
    	@Pattern(regexp="[0-9]{10}",message="{User.userAccount.pattern.error}")
        private Integer userAccount;
    
        //校验非空
        @NotNull(message="{User.userName.null.error}")
        private String userName;
    
        //校验密码长度必须大于6且小于16个字符长度
        //min指定最小长度,max指定最大长度,message指定校验出错时显示的信息
        @Size(min=6,max=16,message="{User.userPassword.length.error}")
        private String userPassword;
    
        private Integer userAge;
        private String userAddress;
        private String userTelephone;
        private String userImage;
    //省略get/set方法
    }

     

  • 编写校验错误信息文件:
  • 在Controller方法中捕捉校验错误信息:

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

    注意:@Validated和BindingResult bindingResult是配对出现(一个@Validated对应一个BindingResult ),并且形参顺序是固定的(一前一后)。
    	@RequestMapping("/")
    	public String userLogin(@Validated User user,BindingResult result){
            //可以通过BindingResult对象获取到所有的错误信息,并且可以通过该对象将错误信息发送到客户端页面
    		List<ObjectError> errors=result.getAllErrors();
    		for(ObjectError error:errors){
    			System.out.println(error.getDefaultMessage());
    		}
    		model.addAttribute("errors", result);
    		return "login";
    	}
    

    4. 分组校验:在pojo中定义校验规则,而pojo是被多个 controller所共用,当不同的controller方法对同一个pojo进行校验,每个controller方法可能会需要需要不同的校验规则。可以定义多个校验分组(其实是一个java接口),分组中定义有哪些规则,每个controller方法使用不同的校验分组

  • 定义校验器分组
    public interface validatorGroup1 {
    	//不需要定义任何方法,只用定义一个接口即可,该接口就表示一个校验器分组
    }
    public interface validatorGroup2 {
    	//不需要定义任何方法,只用定义一个接口即可,该接口就表示一个校验器分组
    }
    //将User类中的校验规则分到到validatorGroup1分组中,通过groups指定,可以写多个分组
    public class User {
    
    	//验证正则表达式,regexp写正则表达式,groups表示将该校验规则添加到validatorGroup1和validatorGroup2两个分组中
    	@Pattern(regexp="[0-9]{10}",message="{User.userAccount.pattern.error}",groups={validatorGroup1.class,validatorGroup2.class})
        private Integer userAccount;
    
        //校验非空
        @NotNull(message="{User.userName.null.error}",groups={validatorGroup1.class})
        private String userName;
    
        //校验密码长度必须大于6且小于16个字符长度
        //min指定最小长度,max指定最大长度,message指定校验出错时显示的信息
        @Size(min=6,max=16,message="{User.userPassword.length.error}",groups={validatorGroup1.class})
        private String userPassword;
        
        private Integer userAge;
        private String userAddress;
        private String userTelephone;
    //省略get/set方法
    }

     

  • 在controller方法中通过校验分组进行校验:@Validated(value={validatorGroup1.class}),通过value指定使用哪个分组中的校验规则,可以指定多个分组
    	@RequestMapping("/")
    	public String userLogin1(@Validated(value={validatorGroup1.class}) User user,BindingResult result){
            //可以通过BindingResult对象获取到所有的错误信息,并且可以通过该对象将错误信息发送到客户端页面
    		List<ObjectError> errors=result.getAllErrors();
    		for(ObjectError error:errors){
    			System.out.println(error.getDefaultMessage());
    		}
    		model.addAttribute("errors", result);
    		return "login";
    	}
    
    	@RequestMapping("/")
    	public String userLogin2(@Validated(value={validatorGroup2.class}) User user,BindingResult result){
            //可以通过BindingResult对象获取到所有的错误信息,并且可以通过该对象将错误信息发送到客户端页面
    		List<ObjectError> errors=result.getAllErrors();
    		for(ObjectError error:errors){
    			System.out.println(error.getDefaultMessage());
    		}
    		model.addAttribute("errors", result);
    		return "login";
    	}

     

4. 异常处理

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

    2. 自定义异常类,该类会针对程序中预期可能会出现的异常,会抛出此类异常

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

	public void setMessage(String message) {
		this.message = message;
	}
}

    3. 定义全局异常处理器,系统遇到异常,在程序中手动抛出,dao抛给service、service给controller、controller抛给前端控制器,前端控制器调用全局异常处理器。全局异常处理器处理思路:解析出异常类型;如果该 异常类型是系统 自定义的异常,直接取出异常信息,在错误页面展示;如果该 异常类型不是系统 自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)。springmvc提供一个HandlerExceptionResolver接口,定义全局异常处理器必须实现该接口

public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {
//		handler就是处理器适配器要执行的Handler对象(也就是Controller中的方法)
//		解析出异常类型
//		如果该 异常类型是系统 自定义的异常,直接取出异常信息,在错误页面展示
		MyException myException = null;
		if(ex instanceof MyException){
			myException = (MyException)ex;
		}else{
			myException = new MyException("未知错误");
		}
		//错误信息
		String message = myException.getMessage();
		ModelAndView modelAndView = new ModelAndView();
		//将错误信息传到页面
		modelAndView.addObject("message", message);
		//指向错误页面
		modelAndView.setViewName("error");
		return modelAndView;
	}
}

    4. 显示错误信息的页面:

    5. 在SpringMVC的配置文件springmvc.xml配置全局异常处理器:

<!--只要实现了HandlerExceptionResolver接口并扫描到SpringMVC应用容器中,就是全局异常处理器-->
<bean class="user_manage.exception.MyHandlerExceptionResolver"></bean>

    6. 测试:只需要在service层或controller层中任意一处需要手动抛出自定义的MyException异常。如果是程序中手动抛出的异常,在错误页面中显示自定义的异常信息;如果不是手动抛出异常说明是一个运行时异常,在错误页面只显示“未知错误”。如果与业务功能相关的异常,建议在service中抛出异常。与业务功能没有关系的异常,建议在controller中抛出。

5. 数据回显

    1. 数据回显指从页面提交请求数据后,如果请求不符合要求或者出现错误,将刚才提交的数据回显到刚才的提交页面。

    2. 实现方法:请求中携带的数据通常通过Controller中的方法形参接收

  • springmvc默认对pojo数据进行回显。pojo数据传入controller方法后,springmvc自动将pojo数据放到request域,然后向指定的jsp页面中发送该请求,在jsp页面中显示数据,使用@ModelAttribute指定pojo回显到页面在request中的key,不一定是用来回显到原页面

    @RequestMapping("/update")
    //ModelAttribute通过该注解就可以将绑定到pojo形参的数据回显到指定的页面中,括号内指定回显到jsp中的key值
    	public String userUpdate(@ModelAttribute("user") User user){
    		//指定返回的jsp页面名
    		return "user";
    	}

     

  • 实际上@ModelAttribute就相当于通过Model形参或返回ModelAndView对象来向指定的jsp页面中发送该请求,在jsp页面中显示数据
    //通过Model实现
    	@RequestMapping("/update")
    	public String userUpdate(User user,Model model){
    		model.addAttribute("userdata", user);
    		return "user";
    	}
    
    //通过ModelAndView实现
    	@RequestMapping("/update")
    	public ModelAndView userUpdate(User user,Model model){
    		ModelAndView mv=new ModelAndView();
    		mv.addObject("userdata", user);
    		mv.setViewName("user");
    		return "user";
    	}

 

 

© 著作权归作者所有

江左煤郎

江左煤郎

粉丝 27
博文 119
码字总数 279370
作品 0
西安
后端工程师
私信 提问
SpringMVC+Spring+Mybatis整合应用(1)

以用户管理系统的开发为例,详细介绍SpringMVC+Spring+Mybatis的整合,并在编写controller的过程中记录SpringMVC中的一些高级应用(会特别标示) 1. 项目整合搭建过程 1. 项目需求:主要实现...

江左煤郎
2018/11/29
73
0
LeeCX - 开源后台管理系统简单介绍

我们在github上开源了一个后台管理系统,使用了前端css框架并且简单的封装了一下,技术的将会不间断更新,详细可以点击原文链接。具体介绍如下: LeeCX 开源后台管理系统,前端基于bootstrap...

风间影月
2017/09/20
0
0
MyBatis(一)-----ssm的整合 跑起来

SpringMVC+Spring+MyBatis 具体的框架整合流程不再赘述 只贴所有配置文件 可以参考:https://www.cnblogs.com/hackyo/p/6646051.html 非框架整合的实例可以学习:https://blog.csdn.net/u01...

废柴
2018/07/05
58
0
SpringMVC+Spring+Mybatis整合应用(3)

实现图片上传 需求:在用户注册页面实现上传图片作为用户头像 1. springmvc中对多部件类型请求数据解析:在页面form中提交enctype="multipart/form-data"的数据时,需要springmvc对multipart...

江左煤郎
2018/12/03
32
0
SpringMvc+Spring+MyBatis 基于注解整合

最近在给学生们讲Spring+Mybatis整合,根据有的学生反映还是基于注解实现整合便于理解,毕竟在先前的工作中团队里还没有人完全舍弃配置文件进行项目开发,由于这两个原因,我索性参考spring官...

java~nick
2017/12/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

STM32进阶之串口环形缓冲区实现

队列的概念 在此之前,我们来回顾一下队列的基本概念: 队列 (Queue):是一种先进先出(First In First Out ,简称 FIFO)的线性表,只允许在一端插入(入队),在另一端进行删除(出队)。 队列...

杰杰1号
7分钟前
2
0
设计模式-建造者模式

建造者模式 定义 将一个复杂对象的构建和它的表示分离,使得同样的构建过程创建出不同的表示。这句话理解起来优点抽象,我们打个简单的比方吧,中国人都喜欢做菜,做菜的时候后会放很多配料...

木本本
10分钟前
4
0
017、xml版本代码生成器配置

1、在pom.xml文件中增加mybatis-generator-maven-plugin插件 <build> <plugins> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>......

北岩
23分钟前
3
0
用jQuery-Easy-UI编写注册页面

本文转载于:专业的前端网站➮用jQuery-Easy-UI编写注册页面 1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content=......

前端老手
31分钟前
2
0
Git ssh配置

生成密钥对 ssh-keygen -t rsa -C "email@email.com"邮箱替换自己邮箱在地址C:\Users\账户\.ssh下,id_rsa、id_rsa.pub两个文件复制文件id_rsa.pub内容到github\gitlab的Settings-> SSH ......

JUKE
38分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部