• SpringMVC09异常处理和类型转化器


     1 public class User {
     2 
     3     private String name;
     4     private Integer age;
     5 
     6     public String getName() {
     7         return name;
     8     }
     9 
    10     public void setName(String name) {
    11         this.name = name;
    12     }
    13 
    14     public Integer getAge() {
    15         return age;
    16     }
    17 
    18     public void setAge(Integer age) {
    19         this.age = age;
    20     }
    21 
    22     public User(String name, Integer age) {
    23         super();
    24         this.name = name;
    25         this.age = age;
    26     }
    27 
    28     public User() {
    29         super();
    30     }
    31 
    32     @Override
    33     public String toString() {
    34         return "User [name=" + name + ", age=" + age + "]";
    35     }
    36 
    37 }
    user实体类
    复制代码
    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 + "]";
        }
    
    }
    复制代码

    对应的异常处理类

    复制代码
    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代码

    其他代码不动   测试 即可!

  • 相关阅读:
    c++智能指针的一些文章
    c++ template(8)模版多态
    空指针赋值分区
    windbg调试命令
    c++ template(5)模板实战
    GetStockObject 理解
    c++ template(6)模板术语
    c++ template(71)模板参数声明
    DirectDraw教程资料
    c++ template(9)trait和Policy
  • 原文地址:https://www.cnblogs.com/HHR-SUN/p/7218521.html
Copyright © 2020-2023  润新知