SpringMVC笔记

  1. 如何通过URL访问到java代码(如何接受请求)------->springMVC执行流程?
  2. 如何接受表单数据?
  3. 如何操作四大作用域?
  4. 如何跳转页面?

SpringMVC简介

SpringMVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。

1.springMVC执行原理

工作流程描述

  1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;
  2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler(controller)对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;

    HandlerMapping接口实现类:

    BeanNameUrlHandlerMapping :通过对比url和bean的name找到对应的对象

    SimpleUrlHandlerMapping :也是直接配置url和对应bean,比BeanNameUrlHandlerMapping功能更多

    DefaultAnnotationHandlerMapping : 主要是针对注解配置@RequestMapping的,已过时

    RequestMappingHandlerMapping :取代了上面一个
  3. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法)

    HandlerAdapter接口实现类:

    HttpRequestHandlerAdapter : 要求handler实现HttpRequestHandler接口,该接口的方法为 void handleRequest(HttpServletRequest request, HttpServletResponse response)也就是 handler必须有一个handleRequest方法

    SimpleControllerHandlerAdapter:要求handler实现Controller接口,该接口的方法为ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response),也就是本工程采用的

    AnnotationMethodHandlerAdapter :和上面的DefaultAnnotationHandlerMapping配对使用的,也已过时

    RequestMappingHandlerAdapter : 和上面的RequestMappingHandlerMapping配对使用,针对 @RequestMapping
  4. 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。在填充Handler的入参过程中,根据你的配置,SpringMVC将帮你做一些额外的工作:

    HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息

    数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
    数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等

    数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
  5. Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
  6. 根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;
  7. ViewResolver 结合Model和View,来渲染视图
  8. 将渲染结果返回给客户端。

2.springMVC环境搭建

第一步,拷贝jar包

此时因为需要处理web请求,所以需要web和webmvc的支持
AOP CORE WEB

第二步,配置DispatcherServlet

打开项目的web.xml,在文件中配置springMVC处理业务的核心servlet:DispatcherServlet,此时如果希望过滤所有请求,那么url-pattern需要配置/,而不能配置/*,代码如下:

<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- 初始化参数:用来赋值springMVC配置文件 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring*.xml</param-value>
</init-param>
<!-- 在tomcat启动的时候创建该对象 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

第三步,引入mvc的注解驱动

springMVC通过策略模式来选择处理的方式,可以根据url和名字等处理,也可以通过注解等方式来处理,现在一般直接采用注解的方式来处理,所以需要引入注解驱动,代码如下:(记得开注解扫描功能)

<mvc:annotation-driven></mvc:annotation-driven>

第四步,指定springMVC的视图处理器

<beanid="resourceViewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<propertyname="prefix"value="/admin/"></property>
<propertyname="suffix"value=".jsp"></property>
</bean>

第五步,准备第一个测试页面(略…)

第六步,准备一个控制器类,用来处理页面的请求

@Controller
@RequestMapping("/userController")
public class UserController {
	@RequestMapping("/login.do")
	public ModelAndView login() {
		ModelAndView mv=new ModelAndView();
		//http://localhost:8090/springMVC1/userController/login.do
		System.out.println("达到控制器.............");
		//视图名称
		mv.setViewName("main");
		mv.addObject("test", "这是测试数据....");
		return mv;
	}
	/*
	 * 通过原生的servletAPI获取
	 */
	@RequestMapping("/login1.do")
	public ModelAndView login1(HttpServletRequest request,HttpServletResponse response) {
		ModelAndView mv=new ModelAndView();
		String name=request.getParameter("name");
		String pad=request.getParameter("pad");
		System.out.println(name+"   "+pad);
		mv.setViewName("main");
		return mv;
	}
	/*
	 * 通过在控制器方法中定义和表单name属性值一直的参数名称一个一个接受表单数据
	 */
	@RequestMapping("/login2.do")
	public ModelAndView login2(@RequestParam("xingming")String name,@RequestParam("pad")String pad) {
		ModelAndView mv=new ModelAndView();
		
		System.out.println(name+"  p------ "+pad);
		mv.setViewName("main");
		return mv;
	}
	/*
	 * 通过实体类接受表单参数
	 */
	@RequestMapping("/login3.do")
	public ModelAndView login3(User user) {
		ModelAndView mv=new ModelAndView();
		System.out.println(user.getName()+"    ---    "+user.getPad());
		mv.setViewName("main");
		return mv;
	}
	/*
	 * 如何接受多选框数据:通过形参直接获取,参数类型必须是数组
	 */
	@RequestMapping("/login4.do")
	public ModelAndView login4(String[] hobby) {
		ModelAndView mv=new ModelAndView();
		System.out.println(hobby.length+"-----------");
		mv.setViewName("main");
		return mv;
	}
	/*
	 * 如何接受多选框数据:通过实体类对象获取,属性类型必须是集合
	 */
	@RequestMapping("/login5.do")
	public ModelAndView login5(User user,String name) {
		ModelAndView mv=new ModelAndView();
		System.out.println(user.getHobby().size()+user.getName()+"-----dfds------"+name);
		mv.setViewName("main");
		return mv;
	}
	/*
	 * 如何接受对象里面的对象类型属性的值
	 */
	@RequestMapping("/login6.do")
	public ModelAndView login6(User user) {
		ModelAndView mv=new ModelAndView();
		System.out.println("用户名:"+user.getName()+"角色:"+user.getRole().getName());
		mv.setViewName("main");
		return mv;
	}
	/*
	 * 接受日期类型的参数
	 */
	@RequestMapping("/login7.do")
	public ModelAndView login7(User user) {
		ModelAndView mv=new ModelAndView();
		System.out.println("用户名:"+user.getName()+"角色:"+user.getRole().getName()+"生日:"+user.getBir()+"年龄:"+user.getAge());
		mv.setViewName("main");
		return mv;
	}
}

3.接收表单数据

(1). 对象属性类型:
在前端的命名:对象名.属性

	角色名称:<input type="text" name="role.roleName"/>

(2).对象集合属性类型:
在前端的命名: 对象名[index].属性

角色1名称:<input type="text" name="roles[2].roleName"/>

(3).多选框数据:
① 如果在形参中单独接收需要使用数组类型
② 如果封装到对象里面那么使用集合类型(List)

(4).日期类型:
在日期属性前添加注解

@DateTimeFormat(pattern="yyyy-MM-dd")
	private Date birth;

4.操作作用域

(1) 如何操作request作用域

  • 通过形参注入HttpServletRequest操作request作用域
  • 放到ModelAndView里面的数据默认放在request作用域中
  • 形参中对象类型的参数默认也会放到request作用域:比如接受表单数据的对象,放到request里面的key默认是参数类型首字母小写
  • 通过在形参中定义Map,ModelMap,Model这些类似于Map集合类型的参数,这些参数藜麦你的数据最终也会放在request作用域中
@RequestMapping("/requestScope.do")
	public ModelAndView requestScope(HttpServletRequest request,User u,Map<String,Object> args) {
		ModelAndView mv=new ModelAndView();
		request.setAttribute("xc", "通过形参放入");
		mv.addObject("mv", "通过mv放入");
		mv.setViewName("main");
		args.put("map", "通过Map放入");
		return mv;
	}

(2)如何操作session作用域

  • 通过形参注入HttpSession即可
  • 通过注解可以吧request里面的数据同步到session作用域 @SessionAttributes("user")
@RequestMapping("/sessionScope.do")
	public ModelAndView sessionScope(HttpSession session,User user) {
		ModelAndView mv=new ModelAndView();
		session.setAttribute("sess", "session数据");
		mv.setViewName("main");
		return mv;
	}

(3)application(servletContext)作用域

  • 通过形参注入HttpSession获取application作用域
@RequestMapping("/appScope.do")
	public ModelAndView appScope(HttpSession session) {
		ModelAndView mv=new ModelAndView();
		session.getServletContext().setAttribute("app", "app..........");
		mv.setViewName("main");
		return mv;
	}
	//可以返回很多类型
	@RequestMapping("/spring.do")
	public String testString(Map<String,Object> args) {
		return "main";
	}

5.跳转页面

- 跳转到页面:

-请求转发:默认的跳转方式
-重定向:必须加redirect前缀,因为重定向不经过视图解析器所以路径必须写全

//重定向到页面
@RequestMapping("/login1.do")
	public ModelAndView login1(User user) {
		ModelAndView mv = new ModelAndView();
		System.out.println("login1...........");
		mv.setViewName("redirect:/admin/main.jsp");
		return mv;
	}
- 跳转到方法:

-请求转发:必须要写forward前缀,路径必须写全路径
-重定向:必须加redirect前缀,路径必须写全路径

//重定向到方法,在一个类中跳转,类路径可以省略
@RequestMapping("/login.do")
	public ModelAndView login() {
		ModelAndView mv = new ModelAndView();
		System.out.println("login.do......redirect");
		mv.setViewName("redirect:login1.do");
		return mv;
	}
//转发到方法
@RequestMapping("/login.do")
	public ModelAndView login() {
		ModelAndView mv = new ModelAndView();
		System.out.println("login.do......forward");
		mv.setViewName("forward:login1.do");
		return mv;
	}
根目录

"/"代表项目根目录,如果不写,根目录为当前路径的上一级

//当前路径http://localhost:8080/springMVC1.1/userController/login.do
mv.setViewName("redirect:admin/main.jsp");
http://localhost:8080/springMVC1.1/userController/admin/main.jsp
转发和重定向的区别

1.redirect不能传递参数,forward在跳转时能够传递参数
2.redirect跳转时,地址栏的地址会发生变化;forward在跳转时,地址栏的地址没有发生变化
3.redirect属于客户端跳转;forward属于服务器端跳转
4.redirect至少发送了2次以上的请求;forward只发了一次请求
5.如果是处理的Post请求,那么:转发时,只能转发到post方法里;但是可以重定向到Get方法里
6.如果是处理的get请求,那么:转发时,只能转发到GET方法里;重定向也只能到达GET方法里

6.字符编码过滤器

spring 帮我们写了一个编码过滤器
在web.xml文件中配置:

<!-- 字符编码过滤器 -->
  <filter>
  		<filter-name>charSetFilter</filter-name>
  		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>  	
		 <init-param>  
        <param-name>forceEncoding</param-name>  
        <param-value>true</param-value>  
     </init-param>  
	
  </filter>
  <filter-mapping>
  		<filter-name>charSetFilter</filter-name>
  		<url-pattern>*.jsp</url-pattern>
  		<url-pattern>*.do</url-pattern>
  </filter-mapping>
     encoding:字符集,即将过滤到的request的字符集设置为encoding指定的值,如UTF-8等;
    forceEncoding:字面意思是强制字符集,但你大可不必按字面意思理解,因为这个参数的值只不过是指定response的字符集是否也设置成encoding所指定的字符集,所以你可以选择设置为true或false。默认为false。

7.文件上传

  1. 设置表单属性
    method必须为post,注意名字不能和实体类属性一样
<form action = "news/addNews.do" method = "post" enctype="multipart/form-data">
<input type="file" name="img"><p>
  1. 配置图片上传视图解析器:可以限制图片上传的大小
<!-- 配置图片上传视图解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 延迟解析 -->
<property name="resolveLazily" value="true"></property>
<!-- 默认字符编码 -->
<property name="defaultEncoding" value="utf-8"></property>
<!-- 上传大小 -->
<property name="maxUploadSize" value="1000000"></property>
</bean>

  1. controller接受上传的图片,并且保存在本地硬盘
 @RequestMapping("fileUpload.do")
    //这里必须用@RequestParam绑定参数
    public ModelAndView fileUpload(@RequestParam("img") CommonsMultipartFile img) {
        ModelAndView mv=new ModelAndView();
        //判断用户有没上传图片
        if(img.getSize()>0) {
            //获取原始文件名称
            String oldFileName=img.getOriginalFilename();//aaa.jpg
            //创建新文件名称
            String newFileName=UUID.randomUUID().toString()+oldFileName.substring(oldFileName.lastIndexOf("."));
            //创建新文件
            File newFile=new File("D:/apache-tomcat-8.0.50/webapps/img/"+newFileName);
            //如果文件不存在我们手动创建出来
            if(!newFile.exists()) {
                newFile.mkdir();
            }
            //把旧文件中的数据写新文件中
            try {
                img.transferTo(newFile);
            } catch (IllegalStateException | IOException e) {
                e.printStackTrace();
            }
            mv.setViewName("redirect:/admin/mian.jsp");
        }
        //给实体类设置图片路径
        //String img = "../img/" + newName;
		//news.setImg(img);
        return mv;
    }

8.全局异常

在controller类中写一个处理异常的方法,通过@ExceptionHandler注解标识的方法可以捕获该handler执行过程中所有controller出现的异常,方便进行异 常的统一处理

/*
	 * 该方法用于全局异常处理
	 * 	该控制器中的所有方法只要出现异常都会进入到该方法处理异常
	 */
	@ExceptionHandler(Exception.class)
	public ModelAndView exce(Exception ex) {
		ModelAndView mv=new ModelAndView();
		if(ex instanceof MaxUploadSizeExceededException) {
			//说明是上传的图片过大
			mv.setViewName("redirect:toAddCar.do");
			//在springmvc里面如果是重定向springmvc会默认的把ModelAndView里面的数据拼在URL后面
			mv.addObject("error", "上传的图片过大....");
		}else if(ex instanceof ArithmeticException ) {
			mv.setViewName("redirect:/error.jsp");
		}
		return mv;
	}

9.拦截器

  1. 拦截器和过滤器的区别
    过滤器:
    ① 属于servlet;
    ② 能拦截所有请求包括.jsp
    ③ 默认情况下拿不到IOC容器中的bean
    ④ 拦截所有请求用 /*
    拦截器:
    ① 属于spring
    ② 只能拦截”.do“结尾的请求
    ③ 可以拿到IOC容器中的bean
    ④ 拦截所有请求用 /**

  2. 拦截器执行过程
    HandlerInterceptor 接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。
    (1 ) preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顾名思义,该方法将在请求处理之前进行调用。SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。
    (2 ) postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解释我们知道这个方法包括后面要说到的afterCompletion 方法都只能是在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用。postHandle 方法,顾名思义就是在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。postHandle 方法被调用的方向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle 方法反而会后执行,这和Struts2 里面的Interceptor 的执行过程有点类型。Struts2 里面的Interceptor 的执行过程也是链式的,只是在Struts2 里面需要手动调用ActionInvocation 的invoke 方法来触发对下一个Interceptor 或者是Action 的调用,然后每一个Interceptor 中在invoke 方法调用之前的内容都是按照声明顺序执行的,而invoke 方法之后的内容就是反向的。
    (3)afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。

  3. 拦截器的使用步骤
    ① 编写一个拦截器类,实现HandlerInterceptor接口

    //不要导错包
    import org.springframework.web.servlet.HandlerInterceptor;
    public class MyInterceptor1 implements HandlerInterceptor{
    	    /*请求(方法)执行完成以后执行
    	     * 做一些清理的工作,以及记录日志的操作
    	     * 该方法执行的前提是preHandle方法返回true
    	     * 逆向执行
    	     */
    	    @Override
    	    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
      		  System.out.println("请求完成之前:拦截器1");
    }
        /*
         * 方法执行完成但是在视图解析(渲染)之前执行
         * 该方法执行的前提是preHandle方法返回true
         * 逆向执行
         */
        @Override
        public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
                throws Exception {
            //在这里可以对ModelAndView对象进行操作
              System.out.println("视图渲染之前:拦截器1");
        }
        /*
         * 请求到达方法之前执行
         * 返回值:当我们想让请求通过拦截器返回true,否则返回false
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse arg1, Object arg2) throws Exception {
            System.out.println("方法之前:拦截器1");
            String path=request.getServletPath();
    	    User loginUser=(User) request.getSession().getAttribute("loginUser");
    	    // /userController/toLogin.do 这个请求不拦截
    	    if(loginUser!=null ||"/userController/toLogin.do".equals(path)) {
    			return true;
    		}else {
    		/*
    		 * 相对路径是相对于访问该资源的路径拼一个相对路径
    		 * 		在拦截器或者过滤器里面拦截到的个请求就是访问该资源(拦截器或者过滤器)请求,
    		 * 		拦截器或者过滤器里面的所有相对路径都是根据拦截到的请求拼接的
    		 * http://localhost:8090/springMVCCar/login.do
    		 * http://localhost:8090/springMVCCar/error.jsp
    		 * http://localhost:8090/springMVCCar/userController/login.do
    		 * http://localhost:8090/springMVCCar/userController/error.jsp
    		 * 
    		 */
    		response.sendRedirect(request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/error.jsp");
    		return false;
    	}
    }
    
    

    ② 在springMVC.xml中配置拦截器

    <!-- 配置一个拦截器 -->
    <mvc:interceptors>
    <mvc:interceptor>
    <!-- 拦截哪些请求-->
    <mvc:mapping path="/news/**"/>
    <bean class="com.zl.interceptor.MyInterceptor"></bean>
    </mvc:interceptor>
    </mvc:interceptors>
    
    拦截器杂碎

    拦截器可以用来拦截一些非法请求,但只能拦截 .do结尾的请求,直接访问jsp页面时,请求是拦截不到的。如果某些页面要进行权限控制,可以放在WEB-INF目录下,该目录下的jsp页面只能经过controller层处理进行访问
    定义路径时:

    @RequestMapping("/toTest.do")
    		public ModelAndView goTest() {
    			ModelAndView mv = new ModelAndView();
    			mv.setViewName("/WEB-INF/test");
    			return mv;
    		}
    

10.表单验证

spring整合第三方的验证框架对表单进行验证,需要导入表单验证框架的jar包
常用的表单验证注解

空检查

@Null:验证对象是否为null
@NotNull:验证对象是否不为null,无法查检长度为0的字符串
@NotBlank:检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格
@NotEmpty:检查约束元素是否为NULL或者是EMPTY,size>0 Booelan检查
@AssertTrue:验证Boolean对象是否为true
@AssertFalse:验证Boolean对象是否为false

长度检查

@Size(min=,max=)验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length(min=,max=)验证对象(CharSequence子类型)长度是否在给定的范围之内

日期检查

@Past:验证Date和Calendar对象是否在当前时间之前
@Future:验证Date和Calendar对象是否在当前时间之后
@Pattern:验证String对象是否符合正则表达式的规则

数值检查

@Min:验证Number和String对象是否大等于指定的值
@Max:验证Number和String对象是否小等于指定的值
@DecimalMax被标注的值必须不大于约束中指定的最大值.这个约束的参数
是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度
@DecimalMin:被标注的值必须不小于约束中指定的最小值.这个约束的参数
是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度
@Digits:验证Number和String的构成是否合法
@Digits(integer=,fraction=):验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度
@Range(min=,max=):检查数字是否介于min和max之间
@CreditCardNumber:信用卡验证
@Email:验证是否是邮件地址,如果为null,不进行验证,算通过验证
@ScriptAssert(lang=,script=,alias=):通过脚本验证

使用步骤

1.在需要进行验证的实体类对象对应的属性上用注解声明验证内容

public class User {
    @NotEmpty(message="用户名不能为空")
    private String name;
    @Size(min=6,max=10,message="密码长度在6-10位之间")
    private String pad;
    private List<String> aihao;
    private Role r;
    @DateTimeFormat(pattern="yyyy-MM-dd")
    @Past(message="生日必须在当前日期之前")
    @NotNull(message="日期不能为空")
    private Date bir;
    //getset省略
}

2.在指定的controller方法中对该对象进行验证

  /*
     * 表单验证:
     *  BindingResult:错误的信息都会包含在该对象中,注意的是该对象必须紧挨验证对象
     */
    @RequestMapping("formVaild.do")
    public ModelAndView formVaild(@Valid User user,BindingResult  br) {
        ModelAndView mv=new ModelAndView();
        //说明验证没有通过
        if(br.hasErrors()) {
            for(ObjectError e:br.getAllErrors()) {
                System.out.println(e.getObjectName()+":"+e.getDefaultMessage());
            }
            mv.setViewName("/login");
        }else {
            mv.setViewName("/admin/main");
        }
        return mv;
    }

3.在页面可以通过特定标签取出错误消息,注意使用form标签的页面必须经过spring

<!--导入form标签库-->
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<form action="UserAction/formVaild.do" method="post">
<!--指定验证的对象的名称-->
<form:form modelAttribute="user">
            用户名:<input id="name" name="name" type="text">
<!--通过该标签获取对应对象对应属性验证未通过的错误消息-->
<form:errors path="name"></form:errors><p>
            密码:<input  id ="pad" name="pad" type="password"><form:errors path="pad"/><p>
            爱好:<input type="checkbox" name="aihao" value="足球">足球
<input type="checkbox" name="aihao" value="篮球">篮球
<input type="checkbox" name="aihao" value="排球">排球<p>
            生日:<input type="text" name="bir"><form:errors path="bir"/><p>
            角色:<input type="text" name="r.name"><p>
<input type="submit" value="登录">
</form:form>
</form>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值