学习目标

第一章-异常处理

知识点-异常处理的思路

1.目标

2.路径

  1. 异常分类

3.讲解

3.1 异常分类

  • 编译时异常,通过try...catch捕获异常|向上抛出异常,否则代码没法写了,从而获取异常信息
  • 运行时异常RuntimeException,通过规范代码开发、测试等,减少运行时异常的发生

3.2 处理思路

  • dao异常通常抛给Service
  • Service异常通常抛给Controller
  • Controller把异常抛给前端控制器(SpringMVC框架)
  • 由前端控制器(DispatcherServlet)把异常交给异常处理器进行处理

1565454676169

4.小结

  1. 异常分类
    1. 编译期异常 : 代码在编译的时候,就已经发现有异常了
    2. 运行期异常: 代码在运行的额时候,才会出现异常。
  2. 异常处理思路
    1. 一级一级的向上抛出,最终交给异常处理器处理

知识点-异常处理的方式

1.目标

2.路径

  1. 异常处理两种方式

  2. 自定义异常处理器

  3. 简单异常处理器

3.讲解

3.1 异常处理两种方式

  • 实现Spring的异常处理器接口HandlerExceptionResolver,自定义异常处理器
    • 需要自己编写代码
    • 也需要进行配置,配置比较简单。只需要在sringmvc.xml里,配置bean对象即可
  • 使用SpringMVC提供好的简单异常处理器SimpleMappingExceptionResolver
    • 不需要自己编写代码
    • 但需要进行配置,配置略微麻烦

3.2 自定义异常处理器

3.2.1 步骤
  1. 创建异常页面,出现异常之后,会打开这个页面给客户端看。
  2. 创建异常处理器,实现HandlerExceptionResolver接口
  3. 在springmvc.xml中配置异常处理器,把自定义异常处理器类声明成为bean对象
3.2.2 配置示例
  • 创建项目,导入依赖
<dependencies>
    <!--servlet-api-->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.1</version>
      <scope>provided</scope>
    </dependency>
    <!--springmvc-->  
    <dependency> 
      <groupId>org.springframework</groupId>  
      <artifactId>spring-webmvc</artifactId>  
      <version>5.1.2.RELEASE</version> 
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>	
  • 编写Controller 模拟抛出异常
package com.itheima.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Controller01 {

    @RequestMapping("/show")
    public void show(int no){
        if(no == 1 ){
            throw  new NullPointerException("出现空指针异常了~!");
        }else if(no == 2) {
            throw  new ClassCastException("出现类型转化异常了~!");
        }else{
            throw  new RuntimeException("出现运行时异常了~!");
        }
    }
}

  • 准备异常页面 error.jsp
<%--
  Created by IntelliJ IDEA.
  User: xiaomi
  Date: 2021/10/6
  Time: 8:58
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h2>服务器开小差了,一会再过来试试吧~!${msg}</h2>

</body>
</html>

  • 创建自定义异常处理器
package com.itheima.exception;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*
    自定义异常处理器
        1. 定义类,实现接口HandlerExceptionResolver
        2. 实现方法resolveException方法,通过返回值来跳转到页面,带上数据显示
        3. 要配置这个类,只要把这个类交给spring管理即可
 */

//@Component
public class MyExceptionResolver implements HandlerExceptionResolver {

    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

        //1. 创建ModelAndView对象
        ModelAndView mv = new ModelAndView();

        //2. 设置跳转的页面
        mv.setViewName("error");

        //3. 设置数据
        mv.addObject("msg" , ex.getMessage());

        return mv;
    }
}

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

        <!--1. 扫描包-->
            <context:component-scan base-package="com.itheima"/>

            <!--2. 注解驱动-->
            <mvc:annotation-driven/>

            <!--3. 视图解析器-->
            <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/"/>
                <property name="suffix" value=".jsp"/>
             </bean>

            <!--4. 静态资源处理-->
            <mvc:default-servlet-handler/>
</beans>

3.3 简单异常处理器

SpringMVC已经定义好了异常处理器,在使用时根据项目情况,配置异常与视图的映射关系

3.3.1 配置步骤
  1. 创建异常页面。可以根据实际需求创建错误页面,比如:
    • 所有异常,都使用同一页面error02.jsp
    • 不同异常,配置不同的错误页面
      • 类转换异常,配置castError.jsp
      • 空指定异常,配置nullError.jsp
      • ...
  2. 在springmvc.xml中,配置简单异常处理器SimpleMappingExceptionResolver
3.3.2 配置示例
  • 准备通用的异常页面error02.jsp
<%--
  Created by IntelliJ IDEA.
  User: xiaomi
  Date: 2021/10/6
  Time: 8:58
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h2>服务器开小差了,一会再过来试试吧~!22222222</h2>

</body>
</html>

  • 空指针异常页面 nullpoint.jsp
<%--
  Created by IntelliJ IDEA.
  User: xiaomi
  Date: 2021/10/6
  Time: 8:58
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h2>服务器开小差了,一会再过来试试吧~!2 空指针异常!</h2>

</body>
</html>

  • 类型转换异常页面 classcast.jsp
<%--
  Created by IntelliJ IDEA.
  User: xiaomi
  Date: 2021/10/6
  Time: 8:58
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h2>服务器开小差了,一会再过来试试吧~!2 类型转换异常!</h2>

</body>
</html>

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

        <!--1. 扫描包-->
      <context:component-scan base-package="com.itheima"/>

      <mvc:annotation-driven/>

      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
          <property name="prefix" value="/"/>
          <property name="suffix" value=".jsp"/>
      </bean>

      <mvc:default-servlet-handler/>

     <!--
        5. 配置简单异常处理器
            5.1 只要配置这个类SimpleMappingExceptionResolver ,注入属性即可
            defaultErrorView : 通用的异常映射,只要报错就会跳转到这个指定的error02页面
            exceptionMappings:给某一种特定的异常,指定的跳转的页面,如果出现了这种特定的异常
                那么springmvc就会跳转到这些页面,而不是通用的页面!
    -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="defaultErrorView" value="error02"/>

        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.NullPointerException">nullpoint</prop>
                <prop key="java.lang.ClassCastException">classcast</prop>
            </props>
        </property>
    </bean>

</beans>

4.小结

  1. 创建一个Java类,实现HandlerExceptionResolver接口:编写代码处理异常
  2. 把创建好的异常处理器注册bean

第二章-拦截器

知识点-拦截器入门

1. 目标

2. 路径

  1. 拦截器概述
  2. 自定义拦截器入门
    • 创建自定义的拦截器实现handlerInterceptor接口,实现preHandler的方法 前置拦截
    • 配置它 springmvc.xml mvc:interceptors标签 1. 拦截的路径规则, 2.处理类

3. 讲解

3.1 拦截器概述

  • SpringMVC中的拦截器 (Interceptor),相当于web开发中的过滤器Filter,用于对Controller进行预处理(前置增强)后处理(后置增强)
  • 多个拦截器形成的一条链,称为拦截器链(Interceptor chain)
    • 当访问被拦截的(具体的目标Controller)方法时,拦截器链中的拦截器就会按照之前定义的顺序被调用
  • 拦截器也是AOP思想的具体实现

3.2 拦截器和过滤器的区别

区别 过滤器Filter 拦截器
使用范围 是Servlet规范的一部分,任何Javaweb项目都可以使用 是SpringMVC自己的,只有使用了SpringMVC框架,才可以使用拦截器
拦截范围 配置了urlPatterns="/*"之后,可以对所有要访问的资源进行拦截 如果配置的是 /** , 会拦截DispatcherServlet抓到的所有资源(请求)
拦截精度 只能拦截某个请求,不能对Servlet里某个方法进行拦截 , 可以精细到拦截Controller里的某个方法
  • 拦截精度答疑:
    • 因为servlet里面写映射地址的时候,是在类上面写的,一个servlet只会有一个映射地址,
    • controller不一样,它里面可以有很多方法,每一个方法都对应一个不同的路径地址。

3.3 快速入门

3.3.1 准备工作
  • 创建maven项目,准备SpringMVC的环境
  • 创建控制器Controller01,准备一个目标方法show()
package com.itheima.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Controller01 {

    @RequestMapping("/show")
    public String show(){
        System.out.println("调用了Controller01的show方法~!");
        return "success";
    }
}


3.3.2 实现步骤
  1. 创建一个Java类,实现HandlerInterceptor接口
    • 重写接口的方法,共三个方法:preHandle, postHandle, afterCompletion
  2. 在springmvc.xml中配置拦截器
3.3.3 功能实现
  • 创建Java类,实现HandlerInterceptor接口
package com.itheima.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*
    定义拦截器
        1. 定义类,实现接口HandlerInterceptor
        2. 重写3个方法 preHandle | postHandle | afterCompletion

 */
public class MyInterceptor implements HandlerInterceptor {

    //拦截到请求的时候调用
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle...");
        return false;
    }

    //controller方法调用之后,执行这个方法
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle...");
    }

    //页面渲染完毕之后,调用这个方法!
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion...");
    }
}
  • 在springmvc.xml中配置拦截器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

        <!--1. 扫描包-->
       <context:component-scan base-package="com.itheima"/>

       <!--2. 注解驱动-->
       <mvc:annotation-driven/>

       <!--3. 视图解析器-->
       <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
           <property name="prefix" value="/"/>
           <property name="suffix" value=".jsp"/>
        </bean>

       <!--4. 静态资源处理-->
       <mvc:default-servlet-handler/>

        <!--5. 配置拦截器-->
        <mvc:interceptors>
            <mvc:interceptor>
                <mvc:mapping path="/show"/>
                <bean class="com.itheima.interceptor.MyInterceptor"/>
            </mvc:interceptor>
        </mvc:interceptors>
</beans>

4. 小结

  1. 拦截器,在进入 controller之前拦截。
  2. 实现HandlerInterceptor接口, preHandler方法, 返回true则可以调用controller方法,false则不会调用controller
  3. 需要在springmvc.xml配置
  4. 作用:权限控制(认证,有没有登陆),微服的链路跟踪, 记录用户的访问日志

知识点-拦截器进阶

1.目标

2.路径

  1. 拦截器的放行
  2. 拦截后跳转
  3. 拦截器的路径
  4. 拦截器的其它方法
  5. 多个拦截器执行顺序

3.讲解

3.2.3.1 拦截器的放行

img

3.2.3.2 拦截后跳转

​ 拦截器的处理结果,莫过于两种:

​ 放行: 如果后面还有拦截器就执行下一个拦截器,如果后面没有了拦截器,就执行Controller方法

​ 拦截: 但是注意,拦截后也需要返回到一个具体的结果(页面,Controller)。

  • 在preHandle方法返回false,通过reque
  • st进行转发,或者通过response对象进行重定向,输出
package com.itheima.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*
    定义拦截器
        1. 定义类,实现接口HandlerInterceptor
        2. 重写3个方法 preHandle | postHandle | afterCompletion

 */
public class MyInterceptor implements HandlerInterceptor {

    /*
        拦截到请求的时候调用, 可以在这个方法里面拦截请求或者放行请求, 到底放行还是不放行,取决于返回值。
            返回true : 即表示放行这个请求,把这个请求交给下一个拦截器或者controller去处理
            返回false : 即表示不放行!不放行请求,也需要对这个请求进行处理,一般有两种方式:
                1. 直接把一句简单的话写出去!
                2. 也可以跳转到某一个页面
                    2.1 跳转页面的时候,可以使用请求转发,也可以使用重定向来跳转
                    2.2 跳转页面的路径写法最好使用绝对路径的写法,尽量不要使用相对路径来跳转!。


     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle...");

        //1. 作出响应: 把一句简单的话写出去!
        //response.setContentType("text/html;charset=utf-8");
        //response.getWriter().write("您没有访问权限!");

        //2. 作出响应: 跳转到某个页面 :index.jsp
        //request.getRequestDispatcher("/index.jsp").forward(request,response);
        //response.sendRedirect("/index.jsp");

        return false;
    }
}

3.2.3.3 拦截器的路径

img

  <!--
            5. 配置拦截器
           mvc:interceptors :  用来配置拦截器的,可以配置很多个拦截器
              mvc:interceptor : 用来配置拦截器,具体的配置
                  mvc:mapping:用于配置拦截什么样的地址
                        path: 指定具体拦截的地址
                  bean : 配置具体的拦截器来,也就是用什么拦截器去拦截上面的请求地址!
        -->
        <mvc:interceptors>
            <mvc:interceptor>
               <!-- 拦截路径解释:
                    1. 可以拦截具体某一种请求路径
                         path="/show" =========== localhost:82/show  可以拦截
                         path="/show" =========== localhost:82/haha  不可以拦截

                    2. 也可以使用通配符来拦截某一类|所有的请求 (仅局限于DispatcherServlet能抓到的请求)
                         /user/**    =========== localhost:82/user/add    localhost:82/user/update/a/b/c  可以拦截
                         /**  =========== 只要是DispatcherServlet能抓到的请求,都能拦截

                         /*   只能匹配一级目录下的任意名字
                         /**  能匹配任意级别目录下的任意名字。

                       2.1 为什么配置成/**了之后, jsp页面不拦截,但是静态资源就会拦截呢?
                            a. DispatcherServlet 映射路径是 / 覆盖了Tomcat了里面的DefaultServlet的 / 所以能抓到静态资源的
                                请求,也就能拦截静态资源
                            b. 之所以没有办法拦截jsp的页面,是因为DispatcherServlet没有办法抓到有关jsp页面的请求,
                                DispatcherServlet 映射路径是 /
                                Tomcaty里面处理jsp页面请求的 JspServlet 映射路径是 *.jsp
                                *.jsp  >  /
                       3. 可以在这里让这个拦截器,不要拦截静态资源。
                            <mvc:exclude-mapping path="/html/**"/>
                            <mvc:exclude-mapping path="/css/**"/>
                            <mvc:exclude-mapping path="/js/**"/>
                -->
                <mvc:mapping path="/**"/>
                <mvc:exclude-mapping path="/html/**"/>
                <mvc:exclude-mapping path="/css/**"/>
                <mvc:exclude-mapping path="/js/**"/>
                <bean class="com.itheima.interceptor.MyInterceptor"/>
            </mvc:interceptor>
        </mvc:interceptors>

3.2.3.4 拦截器的其它方法

  • afterCompletion  在目标方法完成视图层渲染后执行。
  • postHandle  在被拦截的目标方法执行完毕获得了返回值后执行。
  • preHandle 被拦截的目标方法执行之前执行。
package com.itheima.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*
    定义拦截器
        1. 定义类,实现接口HandlerInterceptor
        2. 重写3个方法 preHandle | postHandle | afterCompletion

 */
public class MyInterceptor implements HandlerInterceptor {

   
    ...

    //controller方法调用之后,执行这个方法 , 如果controller方法不执行,那么这个postHandle方法不会执行!
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle...");
    }

    //页面渲染完毕之后,调用这个方法!
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion...");
    }
}

image-20210718160829628

3.2.3.5 多个拦截器执行顺序

​ 我们可以配置多个拦截器, 所以就存在一个优先级问题了.多个拦截器的优先级是按照配置的顺序决定的。

  1. 如果有多个拦截器的,并且最终也执行到了Controller的方法,那么一定会执行他们的postHandle方法和afterCompletion方法
  2. 只要是到了Controller,那么一定会有postHandle方法执行
  3. 如果一开始就不放行,那么只会执行一个preHandle方法
  4. 如果有拦截器链存在,第一个选择放行,第二个(后面的某一个拦截器)选择不放行,那么最后也还是会执行前面放行的拦截器的afterCompletion方法

img

  • 拦截器

拦截器1

package com.itheima.interceptor02;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor01 implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor01::preHandle...");
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor01::postHandle...");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor01::afterCompletion...");
    }
}


拦截器2

package com.itheima.interceptor02;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor02 implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor02::preHandle...");
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor02::postHandle...");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor02::afterCompletion...");
    }
}

拦截器3

package com.itheima.interceptor02;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor03 implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor03::preHandle...");
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor03::postHandle...");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor03::afterCompletion...");
    }
}

  • controller
package com.itheima.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Controller01 {

    @RequestMapping("/show")
    public String show(){
        System.out.println("调用了Controller01 的show方法~!");
        return "success";
    }
}

  • 配置
 <!--拦截器链-->
    <mvc:interceptors>


        <mvc:interceptor>
            <mvc:mapping path="/show"/>
            <bean class="com.itheima.interceptor02.MyInterceptor01"/>
        </mvc:interceptor>

        <mvc:interceptor>
            <mvc:mapping path="/show"/>
            <bean class="com.itheima.interceptor02.MyInterceptor02"/>
        </mvc:interceptor>

        <mvc:interceptor>
            <mvc:mapping path="/show"/>
            <bean class="com.itheima.interceptor02.MyInterceptor03"/>
        </mvc:interceptor>


    </mvc:interceptors>
  • 结果

image-20210826152538621

4.小结

  1. 拦截器属于链式模式

  2. 只有preHandler方法才有返回true 放行,false 拦截

  3. 拦截后也需要对此次请求做出响应(跳转页面|跳转Controller)

  4. 拦截器执行方法顺序 preHandle->postHandle->afterCompletion

  5. 存在拦截器链时,按照配置文件顺序执行,自上而下。先进(preHandle)后出(postHandle,afterCompletion)

  6. 当我们的springmvc配置了静态资源处理,并且拦截器配置成了 /** ,那么拦截器也会拦截静态资源。如果非要让拦截器不拦截静态资源:

    1. 手动指定静态资源的路径,然后拦截器排除具体静态资源

    2. mvc:default-servlet-handler 和 拦截器 /** 还是照常写

      需要在web.xml中,添加DefaultServlet的映射路径

    <servlet-mapping>
    			<servlet-name>default</servlet-name>
    			<url-pattern>*.css</url-pattern>
    			<url-pattern>*.html</url-pattern>
    			<url-pattern>*.js</url-pattern>
    		</servlet-mapping>
    
    1. DispatcherServlet 只拦截*.do

第三章 SSM整合【重点】

案例-环境准备

1.需求

2.分析

  1. 创建数据库和表
  2. 创建Maven工程(web工程)
    • 导入坐标
    • 创建实体类
    • 拷贝log4J日志到工程

3.实现

4.3.1 创建数据库和表结构

create database ssm;
use ssm;
create table account(
    id int primary key auto_increment,
    name varchar(40),
    money double
)character set utf8 collate utf8_general_ci;

insert into account(name,money) values('zs',1000);
insert into account(name,money) values('ls',1000);
insert into account(name,money) values('ww',1000);

4.3.2 创建Maven工程

  • 创建web项目

    image-20200613150119377

  • 导入依赖

<properties>
    <!-- 版本锁定 -->
    <spring.version>5.0.2.RELEASE</spring.version>
    <log4j.version>1.2.17</log4j.version>
    <slf4j.version>1.6.6</slf4j.version>
    <mysql.version>5.1.47</mysql.version>
    <mybatis.version>3.4.6</mybatis.version>
</properties>

<dependencies>
    <!--Spring:ioc和aop,事务-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.4</version>
    </dependency>

    <!--Mybatis-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
    </dependency>
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.4</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>${mybatis.version}</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.2</version>
    </dependency>

    <!--SpringMVC,jstl,json转换-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.6</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

    <!--日志-->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>${slf4j.version}</version>
    </dependency>

    <!--测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.19</version>
    </dependency>
    
    <!-- lombok -->
       <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>
</dependencies>
  • 编写实体类
package com.itheima.bean;

import lombok.Data;

@Data
public class Account {
    private int id;
    private String name;
    private double money;
}

  • 拷贝log4J配置文件到工程

在resource目录下创建一个log4j.properties文件

##设置日志记录到控制台的方式
log4j.appender.std=org.apache.log4j.ConsoleAppender
log4j.appender.std.Target=System.err
log4j.appender.std.layout=org.apache.log4j.PatternLayout
log4j.appender.std.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p %c{1}:%L - %m%n

##设置日志记录到文件的方式
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=mylog.txt
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

##日志输出的级别,以及配置记录方案 debug info   warn  error
log4j.rootLogger= trace,std,file

4 小结

  1. 按步骤操作

案例-整合SpringMVC

1.需求

2.分析

  1. 创建AccountController, 定义方法 添加注解
  2. 创建springmvc.xml(开启包扫描, 注册视图解析器,静态资源处理, 注解驱动)
  3. 配置web.xml(前端控制器, 编码过滤器)
  4. 测试

3.实现

  • 创建AccountController.java
package com.itheima.controller;

import com.itheima.bean.Account;
import com.itheima.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
public class AccountController {

    /*
        查询所有
     */
    @RequestMapping("/findAll")
    public String findAll(){
        System.out.println("调用了AccountController的findAll方法~!");
        return "success";
    }
}

  • 创建springmvc.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--1. 扫描包-->
    <context:component-scan base-package="com.itheima"/>

    <!--2. 注解驱动-->
    <mvc:annotation-driven/>

    <!--3. 视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--4. 静态资源处理-->
    <mvc:default-servlet-handler/>

</beans>
  • 在web.xml里面配置前端控制器和编码过滤器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">

	<!--配置前端控制器 DispatcherServlet-->
		<servlet>
			<servlet-name>dispatcher</servlet-name>
			<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

			<init-param>
				<param-name>contextConfigLocation</param-name>
				<param-value>classpath:springmvc.xml</param-value>
			</init-param>

			<load-on-startup>1</load-on-startup>
		</servlet>

		<servlet-mapping>
			<servlet-name>dispatcher</servlet-name>
			<url-pattern>/</url-pattern>
		</servlet-mapping>


	<!--springmvc已经定义好了过滤器,可以帮助我们解决post请求,中文乱码的问题,我们只需要配置即可-->
		<filter>
			<filter-name>char</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>
		</filter>

		<filter-mapping>
			<filter-name>char</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>
</web-app>

4. 小结

  1. 创建Controller, 创建方法 添加注解
  2. 创建springmvc.xml(开启包扫描, 注册视图解析器,忽略静态资源,开启注解驱动)
  3. 配置web.xml(前端控制器, 编码过滤器)

案例-整合Spring

1. 需求

2. 分析

  1. 编写Service
  2. 在Controller里面注入Service
  3. 在controller里面调用service的方法

3. 实现

  • 编写AccountService.java
package com.itheima.service;

import com.itheima.bean.Account;

import java.util.List;

public interface AccountService {
    /*
    查询所有账户
     */
    List<Account>  findAll();
}

  • 编写AccountServiceImpl.java
package com.itheima.service.impl;

import com.itheima.bean.Account;
import com.itheima.dao.AccountDao;
import com.itheima.service.AccountService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

@Service
public class AccountServiceImpl implements AccountService {

    public List<Account> findAll() {
        System.out.println("调用了AccountServiceImpl的findAll方法~!~");
        return null;
    }
}

  • 在AccountController调用AccountService
package com.itheima.controller;

import com.itheima.bean.Account;
import com.itheima.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
public class AccountController {

    //注入service
    @Autowired
    private AccountService as;

    /*
        查询所有
     */
    @RequestMapping("/findAll")
    public String findAll(){
        System.out.println("调用了AccountController的findAll方法~!");

        //调用service
        List<Account> list = as.findAll();

        System.out.println("list = " + list);

        return "success";
    }
}

4. 小结

  1. 创建业务接口与实现类
  2. 在实现类上加@Service 把交给spring容器管理
  3. AccountController 注入进来 @Autowired, 调用业务方法

案例-整合Mybatis

1. 初级版本 (独立运行)

1.目标

2.路径

  1. 创建Dao接口, 定义方法, 添加注解
  2. 创建SqlMapConfig.xml
  3. 编写Java代码测试

3.讲解

  • 创建AccountDao.java, 添加注解
package com.itheima.dao;

import com.itheima.bean.Account;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.springframework.stereotype.Repository;

import java.util.List;


public interface AccountDao {

    @Select("select * from account")
    List<Account>  findAll();
}
  • 编写MyBatis核心配置文件:SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    


    <!--核心配置文件,包含两部分内容: 如何连接数据库, dao文件|映射在哪里-->
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <package name="com.itheima.dao"/>
    </mappers>

</configuration>
  • 测试运行结果
package com.itheima.test;

import com.itheima.bean.Account;
import com.itheima.dao.AccountDao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;


public class TestAccountDao {

    @Test
    public void testFindAll() throws IOException {

        //1. 读取核心配置文件
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

        //2. 构建构建器SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

        //3. 构建SqlSessionFactory
        SqlSessionFactory sessionFactory = builder.build(is);

        //4. 构建SqlSession
        SqlSession session = sessionFactory.openSession();

        //5. 问SqlSession要dao的代理对象
        AccountDao dao = session.getMapper(AccountDao.class);

        //6. 调用方法
        List<Account> list = dao.findAll();
        System.out.println("list = " + list);

        //7. 收尾: 关闭sqlsession | 提交事务
        session.commit();
        session.close();
    }
}

4.小结

  1. 创建Dao接口, 定义方法, 添加注解
  2. 创建SqlMapConfig.xml
  3. 编写Java测试代码

2. 终极版本(整合运行)

1.需求

2.分析

  • 初级版本存在的问题
    • 连接池还是用的MyBatis自带的 ----> 用第三方的连接池,通过Spring管理
    • 事务还是由MyBatis管理 ----> 通过Spring管理事务
    • 扫描Dao还是由MyBatis加载的 ----> 通过Spring扫描Dao
    • SqlSessionFactory还是我们自己构建的 ----> 通过Spring管理SqlSessionFactory

3. 实现

3.1 Spring接管Mybatis的SqlSessionFactory工厂
  • 创建applicationContext.xml (由于整合Mybatis的配置有点多,所以这里可以写一个新的配置文件。)
  1. 引入外部的数据源(连接池)
  2. 由Spring来管理SqlSessionFactory工厂
  3. 由Spring来扫描dao接口包
  4. 这么做的目的只有一个: 就是顶替掉mybatis的核心配置文件SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--1. 导入外部的连接池(数据源)-->
    <context:property-placeholder location="classpath:db.properties"/>
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${db.driverClass}"/>
        <property name="jdbcUrl" value="${db.jdbcUrl}"/>
        <property name="user" value="${db.user}"/>
        <property name="password" value="${db.password}"/>
    </bean>

    <!--
        2. 由Spring来接管mybatis的SqlSessionFactory工厂
            2.1 由Spring来接管|创建SqlSessionFactory工厂是有好处的。
            2.2 其实在背后Spring不仅创建了SqlSessionFactory的工厂,它还会创建出来SqlSession对象
            2.3 不仅创建了SqlSession对象,还会创建出来dao的代理对象,并且会把这个代理对象丢到
                Spring的容器|工厂里面管理起来。
            2.4 这样子做了之后,我们在service层里面想要dao对象就很简单了,只要让spring注入即可!
     -->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--由于SqlsessionFactory最终是可以操作数据库的,所以要给它注入DataSource-->
        <property name="dataSource" ref="dataSource"/>

        <!--给JavaBean类起别名-->
        <property name="typeAliasesPackage" value="com.itheima.bean"/>

        <!--可以把一部分内容配置在SQLMapConfig.xml里面,然后在这里导入!-->
        <!--<property name="configLocation" value="SqlMapConfig.xml"/>-->
    </bean>

    <!--3. 由Spring来扫描 dao| 映射文件-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.itheima.dao"/>
    </bean>

</beans>
3.2 配置 spring 的事务

mybatis默认不会自动提交: setAutoCommit(false) , 所以对于增伤改的动作,需要提交事务才行。在 applicationContext.xml中编写

    <!--
        4. 由Spring来管理事务
            4.1 Spring管理事务,有一个特征: 就是由管理员来管理事务
            4.2 管理员是谁,得看dao层使用的技术来决定。
                如果dao层使用的技术是 jdbc|mybatis  ======= DataSourceTransactionManager
                如果dao层使用的技术是 hibernate  ========= HibernateTransactionManager
            4.3 操作事务需要用到连接对象,所以要把DataSource对象给注入进来
     -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--配置事务的注解开关-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

3.3 配置applicationContext

由于配置springmvc的时候,写了springmvc.xml , 配置Mybatis的时候,有applicationContext.xml 但是项目启动的时候,解析的入口是在web.xml里面配置。此时存在两个文件,如何抉择呢?有三种方式可供选择。

  1. 方式一:别写applicationContext.xml了, 直接把applicationContext.xml里面的配置定义在springmvc.xml

  2. 方式二: 名字上面下功夫.

    1562231916690

<!--初始化参数:加载配置文件-->
<init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext*.xml</param-value>
</init-param>
  1. 方式三: 在springmvc.xml 引入applicationContext.xml【推荐】

​ 在springmvc.xml中导入applicationContext.xml , 然后在web.xml中只需要引入springmvc.xml即可

<!--5. 导入applicationContext.xml-->
<import resource="applicationContext.xml"/>
3.4 在service中调用dao
package com.itheima.service.impl;

import com.itheima.bean.Account;
import com.itheima.dao.AccountDao;
import com.itheima.service.AccountService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

@Transactional
@Service
public class AccountServiceImpl implements AccountService {

    //注入dao
    @Autowired
    private AccountDao dao;


    public List<Account> findAll() {
        System.out.println("调用了AccountServiceImpl的findAll方法~!");
        return dao.findAll();
    }
}


4. 小结

  • 细节处理
      1. 使用xml管理事务!
      2. 数据源连接的账号密码可以提出来使用properties来写!
      3. mapper能不能使用xml来做!
      4. 别名怎么整?
      5. sqlMapconfig.xml文件还有没有存在的必要!

第四章-HibernateValidator【拓展】

表单校验重要性

表单校验保障了数据有效性、安全性

表单校验分类

校验位置

客户端校验(前端页面)

服务端校验

校验内容与方式

格式校验

  • 客户端:使用js, 利用正则表达式等 (校验)
  • 服务端:使用校验框架(Hibernate Validator) , 如果以后做后台的,那么一般都需要对数据进行校验!

业务校验

  • 客户端:使用ajax发送要校验的数据,后台完成逻辑校验后返回结果 (校验用户名是否可用)
  • 服务端:接收到完整请求后,在执行业务操作前,完成逻辑校验

表单校验规则

  1. 长度:例如用户名长度,评论字符数量

  2. 非法字符:例如用户名组成

  3. 数据格式:例如Email格式、IP地址格式

  4. 边界值:例如转账金额上限,年龄上下限

  5. 重复性:例如用户名是否重复

  6. ...等

表单校验框架

hibernate-validator

Hibernate框架中包含一套独立的校验框架hibernate-validator,实现了JSR303的规范

JSR介绍

JSR全称(Java Specification Requests):Java 规范提案

第303个:提供bean属性相关校验规则

JSR是由JCP(Java Community Process):Java社区提出来的,每年都找各行业的人来提需求,之后就来制定成JSR规提案

依赖说明

tomcat7:搭配hibernate-validator版本5.x.x.Final

tomcat8.5以上的:搭配hibernate-validator版本6.x.x.Final

在这里,我们使用6.1.0.Final

<dependency>
  <groupId>org.hibernate.validator</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>6.1.0.Final</version>
</dependency>

如果使用tomcat7插件运行项目,那么应该使用5.x的版本

    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->  
    <dependency> 
      <groupId>org.hibernate</groupId>  
      <artifactId>hibernate-validator</artifactId>  
      <version>5.1.0.Final</version> 
    </dependency> 

使用案例

创建maven web工程 略

① pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.0</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.8</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.1.0.Final</version>
    </dependency>
    
        <!--tomcat7 ,请使用以下依赖替换上面的6.1.0的版本 -->  
    <!--
   <dependency> 
      <groupId>org.hibernate</groupId>  
      <artifactId>hibernate-validator</artifactId>  
      <version>5.1.0.Final</version> 
    </dependency>  -->  
</dependencies>

② User

package com.itheima.bean;

import lombok.Data;
import org.hibernate.validator.constraints.NotBlank;

import javax.validation.constraints.Min;

@Data
public class User {

    @NotBlank(message = "用户名不能为空!")
    private String username;

    @Min(value = 18 , message = "年龄不达标!")
    private int age;
}

③ UserController

package com.itheima.controller;

import com.itheima.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;
import java.util.List;

@Controller
public class UserController {


    /*
        接收一个用户信息,并且封装到user对象里面去。
            1. 如果无法封装,那么可以从errors参数里面得到错误的信息
            2. 如果希望把这个错误的信息归还给页面显示,可以往model对象里面设置
     */
    @RequestMapping("/add")
    public String add(@Valid User user , Errors errors , Model model){

        //1. 判断校验是否有错误
        if(errors.hasErrors()){ // 表示有错误

            //2. 得到所有的错误信息
            List<FieldError> list = errors.getFieldErrors();

            //3. 遍历集合,取出每一个错误的属性。
            for (FieldError fieldError : list) {

                //4. 得到报错的属性名称
                String field = fieldError.getField();

                //5. 得到报错的具体信息
                String message = fieldError.getDefaultMessage();

                if( message.contains("NumberFormatException")){
                    message = "输入有误!";
                }

                //6. 把信息装到model里面去。
                model.addAttribute(field , message);
            }
            return "index";

        }
        System.out.println("user=" + user);
        //表示没有错误!
        return "success";
    }
}

④ springmvc.xml

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

        <!--1. 扫描包-->
            <context:component-scan base-package="com.itheima"/>

            <!--2. 注解驱动-->
            <mvc:annotation-driven/>

            <!--3. 视图解析器-->
            <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/"/>
                <property name="suffix" value=".jsp"/>
             </bean>

            <!--4. 静态资源处理-->
            <mvc:default-servlet-handler/>
</beans>

⑤ index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>主页</title>
</head>
<body>
<form action="/add" method="post">
    <table>
        <tr>
            <td>用户名</td>
            <td><input name="username"/></td>
            <td>${username}</td>
        </tr>
        <tr>
            <td>年龄</td>
            <td><input name="age"/></td>
            <td>${age}</td>
        </tr>
        <tr>
            <td colspan="3"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form>
</body>
</html>

⑥ success.jsp

<%--
  Created by IntelliJ IDEA.
  User: xiaomi
  Date: 2021/8/26
  Time: 14:50
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h2>这是成功的页面~!</h2>

</body>
</html>

⑦ web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">

	<!--配置前端控制器 DispatcherServlet-->
		<servlet>
			<servlet-name>dispatcher</servlet-name>
			<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

			<init-param>
				<param-name>contextConfigLocation</param-name>
				<param-value>classpath:springmvc.xml</param-value>
			</init-param>

			<load-on-startup>1</load-on-startup>
		</servlet>

		<servlet-mapping>
			<servlet-name>dispatcher</servlet-name>
			<url-pattern>/</url-pattern>
		</servlet-mapping>
</web-app>

总结:

异常处理

1. 自定义异常处理器
	2.2 定义类,实现接口: HandlerExceptionResolver
	2.3. 配置成Bean即可
2. 简单异常处理器
	2.1 不需要去代码了,只需要配置即可,只能让错误出现的时候,跳转到某一个页面上!

拦截器

	1. 拦截器属于SpringMVC的产物,只有使用springmvc环境,才能使用它。
	2. 它主要是用来拦截controller的请求,可以看成是对controller进行前置处理和后置处理。
	3. 怎么使用?
		3.1 定义类,实现接口HandlerInterceptor
		3.2 配置拦截器即可
			<mvc:interceptors>
				<mvc:interceptor>
					 <mvc:mapping path="/show"/>
					 <bean class="拦截器的具体路径"/>
	4. 细节:
		4.1 拦截器里面有3个方法: preHandle |  postHandle  |  afterCompletion
			preHandle : 在执行目标(controller)方法之前调用。
			postHandle :  在执行目标方法之后调用
			afterCompletion: 在页面渲染完毕,调用
		4.2 当我们在拦截器里面拦截下来了某一个请求,那么还是需要对这个请求进行处理的
			可以写一句话出去或者跳转到某个页面显示。否则用户将会看到一片空白!
		4.3 到底是拦截还是放行,取决的是preHandle里面的返回值: 
			true : 放行
			false : 拦截

SSM整合

	SqlSessionFactoryBean : 用于帮助创建Dao的代理对象,丢到spring的容器里面
	MapperScannnerConfiguer : 用于扫描dao的映射文件
posted on 2022-04-23 16:45  ofanimon  阅读(29)  评论(0编辑  收藏  举报
// 侧边栏目录 // https://blog-static.cnblogs.com/files/douzujun/marvin.nav.my1502.css