SpringMVC

9数据格式化

在springmvc.xml中配置:

    <!-- 配置 数据格式化 注解 所依赖的bean
    FormattingConversionServiceFactoryBean:既可以实现格式化、又可以实现类型转换
     -->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <ref bean="myConverter"/>
            </set>
        </property>
    </bean> 

实体类Student

public class Student {
    @NumberFormat(pattern="###,#") 
    private int id;
    
    private String name;
    private int age;
    
    @DateTimeFormat(pattern="yyyy-MM-dd")//格式化:前台传递来的数据,将前台传递来到数据 固定为yyyy-MM-dd
    private Date birthday ;//  2018-12-13
    
    
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    private Address address ;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    
}   

jsp页面:

servlet页面:

        @RequestMapping(value="testDateTimeFormat")//如果Student格式化出错,会将错误信息 传入result中
        public String testDateTimeFormat(Student student , BindingResult result) {
            
            System.out.println(student.getId()+","+student.getName()+","+student.getBirthday());
            
            if(result.getErrorCount() >0) {
                for(FieldError error:  result.getFieldErrors() ) {
                    System.out.println(error.getDefaultMessage());
                }
            }
            return "success";
        }

在页面中输入:


如果输入不满足的日期格式:

页面则会接受失败,报404错误

如果报错,则可以通过加入参数BindingResult result来接收错误

控制台打印:

通过参数BindingResult result来接收错误之后,前台页码则会正常显示,不会报404错误。类似于捕获异常try catch的情形。

数字格式化:

前台页面接收:

后台代码的规范,在实体类中规范

@NumberFormat(pattern="###,#") 
    private int id;

FormattingConversionServiceFactoryBean:既可以实现格式化、又可以实现类型转换

    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <ref bean="myConverter"/>
            </set>
        </property>
    </bean> 

将错误信息通过参数BindingResult result来接收,然后通过Map利用requesScope域将错误传递到页面显示错误信息。否则在参数BindingResult result接收之后,前台页面不会报错误信息。(明明是错误的页面也不会报错误信息,因为被参数所接受处理)

在servlet中将错误信息放入map的requestScope域之中。

在jsp页面遍历显示错误消息:

BindingResult result一定要放到出现错误的实体类之后,否则报错。这个是springmvc框架的约定。

数据校验:

  • JSR303

  • Hibernate Validator(是JSR303的扩充)

a 需要的jar包:

b 加入springmvc的注解驱动:

    <!--此配置是SpringMVC的基础配置,很功能都需要通过该注解来协调  -->
    <mvc:annotation-driven></mvc:annotation-driven>
//会在springmvc容器启动中,自动加载LocalValidatorFactoryBean

c 要想在springmvc中使用三方的校验,还需要实现这个接口:

ValidatorFactory

LocalValidatorFactoryBean是ValidatorFactory的一个实现类。

如果报这个错误,则可能是缺少jar包或者是导入的jar包不正确。

在校验的对象前加这个注解@Valid


注解@Past验证(前台输入的时间必须是当前时间之前的时间)

老师当时讲课的时间:

在前台页面输入当前时间以前的时间:

当输入错误时间的时候,在控制台会显示

@Email注解 验证是不是邮箱格式

11SpringMVC通过Ajax处理json数据

前台jsp页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>

    <script type="text/javascript" src="js/jquery-1.8.3.js"></script>
    <script type="text/javascript">
    
        $(document).ready(function(){
            $("#testJson").click(function(){
                    //通过ajax请求springmvc
                    $.post(
                        "handler/testJson",//服务器地址
                        //{"name":"zs","age":23}
                        function(result){//服务端处理完毕后的回调函数 List<Student> students, 加上@ResponseBody后, students实质是一个json数组的格式
                            for(var i=0;i<result.length ;i++){
                                alert(result[i].id +"-"+result[i].name +"-"+result[i].age);
                            }
                        }
                    );
                
                
            });
            
            
        });
    
    
    </script>

</head>
<body>

    <input type="button" value="testJson" id="testJson" />
</body>

在servlet中:需要加上注解ResponseBody

        @ResponseBody//告诉SpringMVC,此时的返回 不是一个 View页面,而是一个 ajax调用的返回值(Json数组)
        @RequestMapping(value="testJson")
        public List<Student> testJson() {
            //Controller-Service-dao
            //StudentService studentService = new StudentServiceImp();
//          List<Student> students =  studentService.qeuryAllStudent();
            //模拟调用service的查询操作
            
            Student stu1 = new Student(1,"zs",23);
            Student stu2 = new Student(2,"ls",24);
            Student stu3 = new Student(3,"ww",25);
            List<Student> students = new ArrayList<>();
            students.add(stu1) ;
            students.add(stu2) ;
            students.add(stu3) ;
            //模拟调用三层
            return students;
           //返回一个集合,前台ajax接受这个集合
        }

实体类student

json需要的jar包(包的版本需要保持一致)

报这个错,也是jar包不对

在火狐浏览器中

12SpringMVC实现文件上传、拦截器

SpringMVC实现文件上传

和Servlet方式文件上传的本质一样,都是通过commons-fileupload.jar和commons-io.jar来完成的

SpringMVC可以简化文件上传的代码,但是必须满足条件:实现MultipartResolver接口 ;而该接口的实现类SpringMVC也已经提供了CommonsMultipartResolver

实现步骤

  • a导入需要的jar包

commons-fileupload.jar和commons-io.jar

  • b.配置CommonsMultipartResolver将其加入SpringIOC容器

springIOC容器在初始化时候,会自动寻找一个id为MultipartResolver的bean,并将其加入到IOC容器之中。

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" >                                                                              
              <!--文件上传的默认编码 -->
            <property name="defaultEncoding" value="UTF-8"></property>
            <!-- 上传单个文件的最大值,单位Byte;如果-1,表示无限制 -->
            <property name="maxUploadSize"  value="102400"></property>
    </bean>

在jsp页面中:

在servlet中

//文件上传处理方法
        @RequestMapping(value="testUpload") //abc.png
        public String testUpload(@RequestParam("desc") String desc  , @RequestParam("file") MultipartFile file  ) throws IOException {
            
            System.out.println("文件描述信息:"+desc);
            //jsp中上传的文件:file
            
            InputStream input = file.getInputStream() ;//IO
            String fileName = file.getOriginalFilename() ;
                         //文件上传时候的文件名
            
            OutputStream out = new FileOutputStream("d:\\"+fileName) ;
            
            
            byte[] bs = new byte[1024];
            int len = -1;
            while(( len = input.read(bs)) !=-1 ) {
                out.write(bs, 0, len);
            }
            out.close();
            input.close();
            //将file上传到服务器中的 某一个硬盘文件中
        System.out.println("上传成功!");
            
            return "success";
        }

拦截器

拦截器的原理和过滤器相同。

SpringMVC:要想实现拦截器,必须实现一个接口HandlerInterceptor

拦截器的图示

  • a.编写拦截器implements HandlerInterceptor

public class MyInterceptor  implements HandlerInterceptor{

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("拦截请求");  //
        return true;//true:拦截操作之后,放行 ;false:拦截之后不放行,请求终止;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("拦截响应");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("视图(jsp)被渲染完毕");
    }

}

ctrl+shift+r :在eclipse中查找自己编写的代码.java .jsp .html

ctrl+shift+t :在eclipse中查找导入的jar包中的代码

  • b.配置:将自己写的拦截器 配置到springmvcIOC容器中(spring)

    <!-- 将自己写的拦截器 配置到springmvc中(spring);默认拦截全部请求 -->
    <mvc:interceptors>
        
            <!-- 配置具体的拦截路径 -->
            <mvc:interceptor>
                <!-- 指定拦截的路径,基于ant风格 -->
                <mvc:mapping path="/**"/>  
                <!-- 指定拦不截的路径 -->
                <mvc:exclude-mapping path="/handler/testUpload"/> 
                <bean  class="org.lanqiao.interceptor.MyInterceptor"></bean>
            </mvc:interceptor>
            
                <!-- 配置具体的拦截路径 -->
            <mvc:interceptor>
                <!-- 指定拦截的路径,基于ant风格 -->
                <mvc:mapping path="/**"/>  //拦截根目录下的任何子目录
                <!-- 指定拦不截的路径 -->
                <mvc:exclude-mapping path="/handler/testUpload"/> 
                <bean  class="org.lanqiao.interceptor.MySecondInterceptor"></bean>
            </mvc:interceptor>
    </mvc:interceptors>

页面请求点击

请求servlet:

控制台打印:

在拦截器中阻止这次请求

13@ExceptionHandler和@ResponseStatus异常处理

异常处理(@ExceptionHandler该注解标识的方法可以捕获哪些异常,相当于try catch中的catch,对异常进行捕获处理)

在SpringMVC中,处理异常的类实现了HandlerExceptionResolver接口,该接口的每个实现类 都是异常的一种处理方式。@ExceptionHandler标识的方法的参数 必须在异常类型(Throwable或其子类) ,不能包含其他类型的参数。

在servlet中:

异常的处理:

在控制台打印:

图片.png

异常处理路径:最短优先原则

如果有方法抛出一个ArithmeticException异常,而该类中 有2个对应的异常处理法,那么最详细的能处理这个异常的方法会执行:

@ExceptionHandler({Exception.class  })
public ModelAndView handlerArithmeticException2(Exception e) {}

@ExceptionHandler({ArithmeticException.class  })
public ModelAndView handlerArithmeticException1(Exception e) {}

如果发生异常的方法和处理异常的方法不在同一个类之中,那么异常则不可以被捕获。

单独写一个仅仅是处理异常的类(该类加@ControllerAdvice注解,专业处理异常),它可以处理任何类中出现的异常

自定义异常的显示状态ResponseStatusExceptionResolver:自定义异常显示页面 (本类重要作用也是提供注解)@ResponseStatus

枚举类型的错误状态码

创建一个异常类,该类的错误码是注解@ResponseStatus中的value,错误信息是reason

触发的页面

图片.png

前台报错页面

如果发生异常跳转到指定的页面

<!-- SimpleMappingExceptionResolver:以配置的方式 处理异常 -->
    <bean  class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!-- 如果发生异常,异常对象会被保存在  exceptionAttribute的value值中;并且会放入request域中 ;异常变量的默认值是 exception-->
        <!--<property name="exceptionAttribute" value="exception"></property>-->
            <property name="exceptionMappings">
                    <props>
                        <!-- 相当于catch(ArithmeticException ex){ 跳转:error } -->
                        <prop key="java.lang.ArithmeticException">
                            error
                        </prop>
                        <prop key="java.lang.NullPointerException">
                            error
                        </prop>
                    
                    </props>
            </property>
    </bean>

.异常处理的实现类:

DefaultHandlerExceptionResolver:SPringMVC在一些常见异常的基础上(300 500 405),新增了一些异常,例如:

* @see org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
 * @see #handleNoSuchRequestHandlingMethod
 * @see #handleHttpRequestMethodNotSupported  :如果springmvc的处理方法限制为post方式,如果实际请求为get,则会触发此异常显示的页面
 * @see #handleHttpMediaTypeNotSupported
 * @see #handleMissingServletRequestParameter
 * @see #handleServletRequestBindingException
 * @see #handleTypeMismatch
 * @see #handleHttpMessageNotReadable
 * @see #handleHttpMessageNotWritable
 * @see #handleMethodArgumentNotValidException
 * @see #handleMissingServletRequestParameter
 * @see #handleMissingServletRequestPartException
 * @see #handleBindException
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,423评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,147评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,019评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,443评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,535评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,798评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,941评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,704评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,152评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,494评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,629评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,295评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,901评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,978评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,333评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,499评论 2 348

推荐阅读更多精彩内容