我的定位:中高级人才(框架熟练、Java语法精通、数据库会用、Linux会用、中间件会用、有大数据经验!)
开始,我以为自己什么都知道。后来发现,其实我什么都不知道。

SpringMVC09异常处理和类型转化器

public class User {

    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public User(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }

    public User() {
        super();
    }

    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }

}
User实体类

对应的异常处理类

public class UserException extends Exception {

    public UserException() {
        super();
    }

    public UserException(String message) {
        super(message);
    }

}
User异常类
public class NameException extends UserException {

    public NameException() {
        super();
    }

    public NameException(String message) {
        super(message);
    }

}
name异常类
public class AgeException extends UserException {

    public AgeException() {
        super();
    }

    public AgeException(String message) {
        super(message);
    }

}
age异常类
@Controller
@RequestMapping("/user")
public class MyController {
    /**
     * 跳转到/list
     * Model:跳转list方法时 携带的数据
     * @throws UserException 
     */
    @RequestMapping(value = "/add")
    public String add(User user, Model mv) throws UserException {
        System.out.println("进入了add......");
        // 01.模拟异常 System.out.println(5 / 0);

        // 02.模拟异常  name
        if (!user.getName().equals("admin")) {
            throw new NameException("用户名错误!");
        }
        // 03.模拟异常 age
        if (user.getAge() > 50) {
            throw new AgeException("年龄不合法!");
        }

        mv.addAttribute("name", user.getName()).addAttribute("age",
                user.getAge());
        return "redirect:list";
    }

    @RequestMapping(value = "/list")
    public String list(User user) {
        System.out.println("进入了list......");
        System.out.println(user.getName());
        System.out.println(user.getAge());
        return "/success.jsp";
    }

}
对应的controller代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">


<!-- 配置需要扫描的包 -->
<context:component-scan base-package="cn.bdqn.controller"/>
<!-- 开启注解 -->
<mvc:annotation-driven/>

<!-- 设置异常处理 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
   <!-- 01.出现异常时 跳转的界面-->
    <property name="defaultErrorView" value="/errors/error.jsp"/>
    <!-- 02.给用户提示信息 -->
    <property name="exceptionAttribute" value="ex"/>
    <!-- 03.自定义的异常跳转界面  -->
    <property name="exceptionMappings">
     <props>
       <prop key="cn.bdqn.exception.NameException">/errors/nameError.jsp</prop>
       <prop key="cn.bdqn.exception.AgeException">/errors/ageError.jsp</prop>
     </props>
     
    </property>
</bean>
springmvc-servlet.xml文件

需要的界面

 <body>
  <form action="user/add" method="post">
  <!-- 必须是User类中对应的属性名 -->
    用户名:<input type="text"  name="name">
     年龄:<input type="text"  name="age">
  <button type="submit">提交</button>
  </form>
  
  </body>
index.jsp
 <body>
   <h1>错误界面</h1>
   ${ex.message}
  </body>
error.jsp
<body>
   <h1>name错误界面</h1>
   ${ex.message}
  </body>
nameError.jsp
 <body>
   <h1>age错误界面</h1>
   ${ex.message}
  </body>
ageError.jsp

 ====================自定义异常处理器===========================

/**
 * 自定义的异常处理器  implements HandlerExceptionResolver
 */
public class MyExceptionResolver implements HandlerExceptionResolver {
    /**
     * handler:就是我们的controller
     * ex:controller出现的异常信息
     */
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("ex", ex);// 保存异常信息
        mv.setViewName("/errors/error.jsp"); // 其他异常处理
        if (ex instanceof NameException) {
            mv.setViewName("/errors/nameError.jsp");
        }
        if (ex instanceof AgeException) {
            mv.setViewName("/errors/ageError.jsp");
        }
        return mv;
    }

}
创建自定义的异常处理器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">


<!-- 配置需要扫描的包 -->
<context:component-scan base-package="cn.bdqn.controller"/>
<!-- 开启注解 -->
<mvc:annotation-driven/>

<!-- 设置自定义的异常处理器-->
<bean class="cn.bdqn.controller.MyExceptionResolver"/>



</beans>
修改springmvc-servlet.xml

其他代码不需要更改!测试即可!

===================使用注解的方式实现异常处理=======================

删除上个例子中xml文件 配置的自定义异常处理器

/**
 *03.提取出来一个处理异常的类
 */
@Controller
public class BaseController { // 专门来处理 异常的

    @ExceptionHandler
    // 其他的异常
    public ModelAndView defaultException(Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("ex", ex);// 保存异常信息
        mv.setViewName("/errors/error.jsp"); // 其他异常处理
        return mv;
    }

    @ExceptionHandler(NameException.class)
    // name的异常
    public ModelAndView nameException(Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("ex", ex);// 保存异常信息
        mv.setViewName("/errors/nameError.jsp");
        return mv;
    }

    @ExceptionHandler(AgeException.class)
    // age的异常
    public ModelAndView ageException(Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("ex", ex);// 保存异常信息

        mv.setViewName("/errors/ageError.jsp");
        return mv;
    }
}
BaseController
@Controller
@RequestMapping("/user")
public class MyController extends BaseController {
    /**
     * 跳转到/list
     * Model:跳转list方法时 携带的数据
     * @throws UserException 
     */
    @RequestMapping(value = "/add")
    public String add(User user, Model mv) throws UserException {
        System.out.println("进入了add......");
        // 01.模拟异常
        // System.out.println(5 / 0);

        // 02.模拟异常 name
        if (!user.getName().equals("admin")) {
            throw new NameException("用户名错误!");
        }
        // 03.模拟异常 age
        if (user.getAge() > 50) {
            throw new AgeException("年龄不合法!");
        }

        mv.addAttribute("name", user.getName()).addAttribute("age",
                user.getAge());
        return "redirect:list";
    }

    @RequestMapping(value = "/list")
    public String list(User user) {
        System.out.println("进入了list......");
        System.out.println(user.getName());
        System.out.println(user.getAge());
        return "/success.jsp";
    }

    /**
     * 01.所有的异常的都在一个方法中 处理
     
    @ExceptionHandler
    public ModelAndView resolveException(Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("ex", ex);// 保存异常信息
        mv.setViewName("/errors/error.jsp"); // 其他异常处理
        if (ex instanceof NameException) {
            
            mv.setViewName("/errors/nameError.jsp");
        }
        if (ex instanceof AgeException) {
            
            mv.setViewName("/errors/ageError.jsp");
        }
        return mv;
    }*/

    /**
     * 02.针对于每个异常
    
    @ExceptionHandler
    // 其他的异常
    public ModelAndView defaultException(Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("ex", ex);// 保存异常信息
        mv.setViewName("/errors/error.jsp"); // 其他异常处理
        return mv;
    }

    @ExceptionHandler(NameException.class)
    // name的异常
    public ModelAndView nameException(Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("ex", ex);// 保存异常信息
        mv.setViewName("/errors/nameError.jsp");
        return mv;
    }

    @ExceptionHandler(AgeException.class)
    // age的异常
    public ModelAndView ageException(Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("ex", ex);// 保存异常信息

        mv.setViewName("/errors/ageError.jsp");
        return mv;
    } */
}
Controller中的代码

==================类型转化器============================

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML>
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>
  <body>
  ${ex.message}
  <form action="user/login" method="post">
  <!-- 必须是User类中对应的属性名 -->
    出生日期:<input type="text"  name="birthday" value="${birthday}"> ${birthdayError}<br/>
     年龄:<input type="text"  name="age" value="${age}"> ${ageError}
  <button type="submit">提交</button>
  </form>
  
  </body>
</html>
index.jsp页面
@Controller
@RequestMapping("/user")
public class MyController {
    /**
     * 登录
     * Date  能自动类型转换        2015/    02/02
     */
    @RequestMapping(value = "/login")
    public ModelAndView login(int age, Date birthday) {
        System.out.println("进入了login......");
        System.out.println(age);
        System.out.println(birthday);
        ModelAndView mv = new ModelAndView();
        mv.addObject("age", age).addObject("birthday", birthday)
                .setViewName("/success.jsp");
        return mv;
    }

    /**
     * TypeMismatchException 类型转换不了的时候  抛出的异常
     * HttpServletRequest request:数据的回显
     * Exception ex:给用户提示
     */
    @ExceptionHandler(TypeMismatchException.class)
    public ModelAndView exceptionAge(HttpServletRequest request, Exception ex) {
        ModelAndView mv = new ModelAndView();
        String age = request.getParameter("age");
        String birthday = request.getParameter("birthday");
        // 让用户看到错误的信息
        String message = ex.getMessage();
        if (message.contains(age)) {
            mv.addObject("ageError", "年龄输入有误!");
        }
        if (message.contains(birthday)) {
            mv.addObject("birthdayError", "日期输入有误!");
        }

        mv.addObject("age", age).addObject("birthday", birthday)
                .addObject("ex", ex).setViewName("/index.jsp");

        return mv;
    }

}
Controller
/**
 * 
 * 自定义的类型转化器
 *  @param <S> the source type  前台表单中肯定是string
 * @param <T> the target type
 *
 * public interface Converter<S, T> {
 */
public class MyDateConverter implements Converter<String, Date> {
    /**
     * source:前台传递来的字符串
     */
    public Date convert(String source) {
        // 类型转化
        SimpleDateFormat sdf = getDate(source);
        Date parse = null;
        try {
            parse = sdf.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse;
    }

    /**
     * @param source 传递来的日期格式的字符串
     * 
     */
    private SimpleDateFormat getDate(String source) {
        SimpleDateFormat sdf = new SimpleDateFormat();
        // 判断
        if (Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$", source)) {
            sdf = new SimpleDateFormat("yyyy-MM-dd");
        } else if (Pattern.matches("^\\d{4}/\\d{2}/\\d{2}$", source)) {
            sdf = new SimpleDateFormat("yyyy/MM/dd");
        } else if (Pattern.matches("^\\d{4}\\d{2}\\d{2}$", source)) {
            sdf = new SimpleDateFormat("yyyyMMdd");
        } else {
            /**
             * 都不匹配了   就让它抛出 TypeMismatchException异常
             *     public TypeMismatchException(Object value, Class<?> requiredType) {
             * vallue 值能对应requiredType 类型 就不会出现异常
             *  我们就得写一个不能转换的
             */
            throw new TypeMismatchException("", Date.class);
        }
        return sdf;
    }
}
类型转化器代码
public class User {

    private String name;
    private Date birthday;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User [name=" + name + ", birthday=" + birthday + ", age=" + age
                + "]";
    }

    public User(String name, Date birthday, Integer age) {
        super();
        this.name = name;
        this.birthday = birthday;
        this.age = age;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public User() {
        super();
    }

}
需要的User实体类

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">


<!-- 配置需要扫描的包 -->
<context:component-scan base-package="cn.bdqn.controller"/>
<!-- 开启注解 -->
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 注册我们自己创建的类型转换器  -->
<bean  id="myDateConverter" class="cn.bdqn.controller.MyDateConverter"/>

<!-- 创建一个类型转换器工厂 来加载我们自己创建的类型转换器  -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
   <property name="converters">
     <set>
      <ref bean="myDateConverter"/><!--如果需要配置多个类型转化器  只需要增加 ref节点 -->
     </set>
   </property>

</bean>


</beans>
springmvc-servlet.xml文件
<body>
  <h1>webroot   success页面</h1>
  ${birthday}<br/>
  ${age}
  </body>
success.jsp页面

======================初始化类型绑定===================

在上面的例子中修改xml文件内容! 也就是把之前的类型转换器 删掉

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">


<!-- 配置需要扫描的包 -->
<context:component-scan base-package="cn.bdqn.controller"/>
<!-- 开启注解 -->
<mvc:annotation-driven/>



</beans>
springmvc-servlet.xml文件内容

修改controller中的代码

@Controller
@RequestMapping("/user")
public class MyController {
    /**
     * 登录
     * Date  能自动类型转换        2015/    02/02
     */
    @RequestMapping(value = "/login")
    public ModelAndView login(int age, Date birthday) {
        System.out.println("进入了login......");
        System.out.println(age);
        System.out.println(birthday);
        ModelAndView mv = new ModelAndView();
        mv.addObject("age", age).addObject("birthday", birthday)
                .setViewName("/success.jsp");
        return mv;
    }

    /**
     * 初始化参数的绑定
     * binder.registerCustomEditor(Date.class, new CustomDateEditor(df, true))
     * Date.class:需要转换成的类型
     * new CustomDateEditor:类型编辑器
     * true代表 允许日期格式为空
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); // 只能匹配这种格式
        binder.registerCustomEditor(Date.class, new CustomDateEditor(df, true));
    }
}
匹配一种日期格式的controller

之后可以运行 测试!

 

创建自己定义的类型编辑器  来完成多种日期格式的绑定

/**
 * 
 * 自定义的类型编辑器
 */
public class MyDateEditor extends PropertiesEditor {
    @Override
    public void setAsText(String source) throws IllegalArgumentException {
        SimpleDateFormat sdf = getDate(source);
        Date parse = null;
        // 类型转化
        try {
            parse = sdf.parse(source);
            setValue(parse);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param source 传递来的日期格式的字符串
     * 
     */
    private SimpleDateFormat getDate(String source) {
        SimpleDateFormat sdf = new SimpleDateFormat();
        // 判断
        if (Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$", source)) {
            sdf = new SimpleDateFormat("yyyy-MM-dd");
        } else if (Pattern.matches("^\\d{4}/\\d{2}/\\d{2}$", source)) {
            sdf = new SimpleDateFormat("yyyy/MM/dd");
        } else if (Pattern.matches("^\\d{4}\\d{2}\\d{2}$", source)) {
            sdf = new SimpleDateFormat("yyyyMMdd");
        } else {
            /**
             * 都不匹配了   就让它抛出 TypeMismatchException异常
             *     public TypeMismatchException(Object value, Class<?> requiredType) {
             * vallue 值能对应requiredType 类型 就不会出现异常
             *  我们就得写一个不能转换的
             */
            throw new TypeMismatchException("", Date.class);
        }
        return sdf;
    }
}
MyDateEditor

修改controller中的代码

package cn.bdqn.controller;

import java.util.Date;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/user")
public class MyController {
    /**
     * 登录
     * Date  能自动类型转换        2015/    02/02
     */
    @RequestMapping(value = "/login")
    public ModelAndView login(int age, Date birthday) {
        System.out.println("进入了login......");
        System.out.println(age);
        System.out.println(birthday);
        ModelAndView mv = new ModelAndView();
        mv.addObject("age", age).addObject("birthday", birthday)
                .setViewName("/success.jsp");
        return mv;
    }

    /**
     * 初始化参数的绑定
     * binder.registerCustomEditor(Date.class, new CustomDateEditor(df, true))
     * Date.class:需要转换成的类型
     * new CustomDateEditor:类型编辑器
     * true代表 允许日期格式为空
     
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); // 只能匹配这种格式
        binder.registerCustomEditor(Date.class, new CustomDateEditor(df, true));
    }*/

    /**
     * 绑定多种日期格式
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        // 使用自己定义的类型编辑器new MyDateEditor()
        binder.registerCustomEditor(Date.class, new MyDateEditor());
    }
}
Controller代码

 

 

其他代码不动   测试 即可!

posted @ 2017-06-30 09:40  想太多先森  阅读(109)  评论(0编辑  收藏  举报