springMVC

springMVC

1. 介绍

1.1 概述
  1. SpringMVC 简介 SpringMVC 也叫 Spring web mvc。是 Spring 框架的一部分,是在 Spring3.0 后发布的。 专门是做web开发的。理解是servlet的一个升级。

web开发底层是servlet , 框架是在servlet基础上面加入一些功能,让你做web开发方便。

SpringMVC:是基于spring的一个框架, 实际上就是spring的一个模块,SpringMVC就是一个Spring。 Spring是容器,ioc能够管理对象,使用, @Component, @Repository, @Service, @Controller。 SpringMVC能够创建对象, 放入到容器(SpringMVC容器), springmvc容器中放的是控制器对象

我们要做的是 使用@Contorller创建控制器对象, 把对象放入到springmvc容器中, 把创建的对象作为控制器使用这个控制器对象能接收用户的请求, 显示处理结果,就当做是一个servlet使用。

使用@Controller注解创建的是一个普通类的对象, 不是Servlet。 springmvc赋予了控制器对象一些额外的功能。

  1. SpringMVC 优点:

    • 基于 MVC 架构 基于 MVC 架构,功能分工明确。解耦合,

    • 容易理解,上手快;使用简单。开发一个注解的 SpringMVC 项目,SpringMVC也是轻量级的,jar 很小。不依赖的特定的接口和类。

    • 作 为 Spring 框 架 一 部分,能够使用 Spring 的 IoC 和 Aop。方便整合 Strtus,MyBatis,Hiberate,JPA 等其他框架。

    • SpringMVC 强化注解的使用,在控制器,Service,Dao 都可以使用注解。方便灵活。 使用@Controller 创建处理器对象,@Service 创建业务对象,@Autowired 或者@Resource 在控制器类中注入 Service, Service 类中注入 Dao。

  2. 执行顺序:

web开发底层是servlet, springmvc中有一个对象是Servlet : DispatherServlet(中央调度器)
DispatherServlet: 负责接收用户的所有请求, 用户把请求给了DispatherServlet, 之后DispatherServlet把请求转发给我们的Controller对象, 最后是Controller对象处理请求。

index.jsp--------DispatherServlet(Servlet)----------转发,分配给------------Controller对象(@Controller注解创建的对象)

<!--声明,注册springmvc的核心对象DispatcherServlet
    需要在tomcat服务器启动后,创建DispatcherServlet对象的实例。
    为什么要创建DispatcherServlet对象的实例呢?
    因为DispatcherServlet在他的创建过程中,会同时创建springmvc容器对象,
    读取springmvc的配置文件, 把这个配置文件中的对象都创建好,当用户发起
    请求时就可以直接使用对象了。

    servlet的初始化会执行init()方法。DispatcherServlet在init ()中{
        //创建容器,读取配置文件
        WebApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc.xml");
        //把容器对象放入到ServletContext中
        getServletContext( ). setAttribute(key, ctx);
        }


        启动tomcat报错,读取这个文件  /WEB-INF/<servlet-name>-servlet.xml
        springmvc创建容器对象时,读取的配置文件默认是/WEB-INF/<servlet-name>-servlet.xml

-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <!--自定义springmvc读取的配置文件的位置-->
        <init-param>
            <!--springmvc的配置文件的位置的属性-->
            <param-name>contextConfigLocation</param-name>
            <!--指定自定义文件的位置-->
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>

        <!--在tomcat启动后, 创建Servlet对象
            load-on-startup:表示tomcat启动后创建对象的顺序。它的值是整数,数值越小,tomcat创建对象的时间越早。
            大于等于0的整数。
        -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>

        <!--
            使用框架的时候,url-pattern可以使用两种值
            1.使用扩展名方式,语法*.xxxx ,xxx是自定义的扩展名。 常用的方式*.do, *.action, *.mvc等等
                http://localhost:8080/myweb/some.do
                http://localhost:8080/myweb/other.do

            2.使用斜杠"/"
        -->

        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

springmvc请求的处理流程:

1)发起some.do
2)tomcat(web.xml–url-pattern知道 *.do的请求给DispatcherServlet)
3)DispatcherServlet(根据springmvc.xml配置知道 some.do—doSome())
4)DispatcherServlet把some.do转发个MyController.doSome()方法
5)框架执行doSome()把得到ModelAndView进行处理, 转发到show.jsp

上面的过程简化的方式
some.do—DispatcherServlet—MyController

在这里插入图片描述


1.2 使用 SpringMVC 框架 web 请求处理顺序:

在这里插入图片描述

1.3 SpringMVC 的 MVC 组件:

在这里插入图片描述

1.4 SpringMVC 执行流程

在这里插入图片描述

执行流程简单分析

(1)浏览器提交请求到中央调度器

(2)中央调度器直接将请求转给处理器映射器。

(3)处理器映射器会根据请求,找到处理该请求的处理器,并将其封装为处理器执行链后 返回给中央调度器。

(4)中央调度器根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器。

(5)处理器适配器调用执行处理器。

(6)处理器将处理结果及要跳转的视图封装到一个对象 ModelAndView 中,并将其返回给 处理器适配器。

(7)处理器适配器直接将结果返回给中央调度器。

(8)中央调度器调用视图解析器,将 ModelAndView 中的视图名称封装为视图对象。

(9)视图解析器将封装了的视图对象返回给中央调度器

(10)中央调度器调用视图对象,让其自己进行渲染,即进行数据填充,形成响应对象。

(11)中央调度器响应浏览器。

2. SpringMVC 注解式开发

2.1 @RequestMapping 定义请求规则
2.1.1 指定模块名称

通过@RequestMapping 注解可以定义处理器对于请求的映射规则。该注解可以注解在方法上,也可以注解在类上,但意义是不同的。value 属性值常以“/”开始。

@RequestMapping 的 value 属性用于定义所匹配请求的 URI。但对于注解在方法上与类上,其value属性所指定的URI,意义是不同的。

一个@Controller 所注解的类中,可以定义多个处理器方法。当然,不同的处理器方法 所匹配的 URI 是不同的。这些不同的 URI 被指定在注解于方法之上的@RequestMapping 的 value 属性中。但若这些请求具有相同的 URI 部分,则这些相同的 URI,可以被抽取到注解在 类之上的@RequestMapping 的 value 属性中。此时的这个 URI 表示模块的名称。URI 的请求 是相对于 Web 的根目录。

换个角度说,要访问处理器的指定方法,必须要在方法指定 URI 之前加上处理器类前定 义的模块名称

2.1.2 对请求提交方式的定义

对于@RequestMapping,其有一个属性 method,用于对被注解方法所处理请求的提交 方式进行限制,即只有满足该 method 属性指定的提交方式的请求,才会执行该被注解方法。

Method 属性的取值为 RequestMethod 枚举常量。常用的为 RequestMethod.GET 与 RequestMethod.POST,分别表示提交方式的匹配规则为 GET 与 POST 提交。

在这里插入图片描述

也就是说,只要指定了处理器方法匹配的请求提交方式为 POST,则相当于指定了请求 发送的方式:要么使用表单请求,要么使用 AJAX 请求。其它请求方式被禁用。

当然,若不指定 method 属性,则无论是 GET 还是 POST 提交方式,均可匹配。即对于 请求的提交方式无要求。

2.2 处理器方法的参数

处理器方法可以包含以下四类参数,这些参数会在系统调用时由系统自动赋值,即程序员可在方法内直接使用。

  • HttpServletRequest
  • HttpServletResponse
  • HttpSession
  • 请求中所携带的请求参数
2.2.1 逐个参数接收

保证请求参数名与该请求处理方法的参数名相同即可。

在这里插入图片描述

逐个接收请求参数:
要求:处理器(控制器)方法的形参名和请求中参数名必须一致。 同名的请求参数赋值给同名的形参。

框架接收请求参数

  1. 使用request对象接收请求参数

    string strName = request.getParameter( "name"" ) ;
    string strAge = request.getParameter( "age") ;
    
  2. springmvg 框架通过DispatcherServlet调用MyController的doSome() 方法
    调用方法时,按名称对应,把接收的参数赋值给形参
    doSome ( strName , Integer. valueOf(strAge) )
    框架会提供类型转换的功能,能把string转为int,long,float,double等类型。

2.2.2 请求参数中文乱码问题

对于前面所接收的请求参数,若含有中文,则会出现中文乱码问题。

Spring 对于请求参数中的中文乱码问题,给出了专门的字符集过滤器:spring-web-5.2.5.RELEASE.jar 的 org.springframework.web.filter 包下的 CharacterEncodingFilter 类。

解决方案:

在 web.xml 中注册字符集过滤器,即可解决 Spring 的请求参数的中文乱码问题。不过, 最好将该过滤器注册在其它过滤器之前。因为过滤器的执行是按照其注册顺序进行的。

<!--注册声明过滤器,解决post请求乱码的问题-->
<filter>
    <filter-name>characterEncodingFilter</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>
    <!-- 强制请求对象( HttpServletRequest )使用encoding编码的值 -->
    <init-param>
        <param-name>forceRequestEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
    <!--强制应答对象( HttpServletResponse )使用encoding编码的值-->
    <init-param>
        <param-name>forceResponseEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<!--        /*:表示强制所有的请求先通过过滤器处理。   -->
<filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
2.2.3 校正请求参数名@RequestParam

所谓校正请求参数名,是指若请求 URL 所携带的参数名称与处理方法中指定的参数名不相同时,则需在处理方法参数前,添加一个注解**@RequestParam(“请求参数名”)**,指定请 求 URL 所携带参数的名称。该注解是对处理器方法参数进行修饰的。value 属性指定请求参 数的名称。

请求中参数名和处理器方法的形参名不一样
@RequestParam: 逐个接收请求参数中, 解决请求中参数名形参名不一样的问题
属性:

  1. value请求中的参数名称

  2. required 是一个boolean ,默认是true
    true :表示请求中必须包含此参数。

    false:可以没有此参数

位置:在处理器方法的形参定义的前面

在这里插入图片描述

2.2.4 对象参数接收

将处理器方法的参数定义为一个对象,只要保证请求参数名与这个对象的属性同名即可。

处理器方法形参是java对象,这 个对象的属性名和请求中参数名一样的
框架会创建形参的java对象,给属性赋值。 请求 中的参数是name,框架会 调用setName( )

在这里插入图片描述

2.3 处理器方法的返回值

使用@Controller 注解的处理器的处理器方法,其返回值常用的有四种类型:

  • 第一种:ModelAndView

  • 第二种:String

  • 第三种:无返回值 void

  • 第四种:返回自定义类型对象 根据不同的情况,使用不同的返回值。

2.3.1 返回 ModelAndView

要数据和视图返回ModelAndView,对视图执行forward。

若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据此时 处理器方法返回 ModelAndView 比较好。当然,若要返回 ModelAndView,则处理器方法中 需要定义 ModelAndView 对象。

在使用时,若该处理器方法只是进行跳转而不传递数据,或只是传递数据而并不向任何资源跳转(如对页面的 Ajax 异步响应),此时若返回 ModelAndView,则将总是有一部分多余:要么 Model 多余,要么 View 多余。即此时返回 ModelAndView 将不合适。

2.3.2 返回 String

处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析可以将其转换为物理视图地址

string:表示视图,可以逻辑名称,也可以是完整视图路径

返回内部资源逻辑视图名

若要跳转的资源为内部资源,则视图解析器可以使用 InternalResourceViewResolver 内部资源视图解析器。此时处理器方法返回的字符串就是要跳转页面的文件名去掉文件扩展名后 的部分。这个字符串与视图解析器中的 prefix、suffix 相结合,即可形成要访问的 URI。

<!--声明 springmvc框架中的视图解析器, 帮助开发人员设置视图文件的路径-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--前缀:视图文件的路径-->
    <property name="prefix" value="/WEB-INF/view/" />
    <!--后缀:视图文件的扩展名-->
    <property name="suffix" value=".jsp"/>
</bean>

逻辑视图名称:

@RequestMapping(value = "/returnString-view.do")
public String doReturnView(HttpServletRequest request, String name, Integer age){
    System.out.println("doReturnView,name="+name+"age="+age);
    //可以自己手工添加数据到request作用域
    request.setAttribute("myname",name);
    request.setAttribute("myage",age);

    //show :逻辑视图名称 ,项目中配置了视图解析器
    //框架对视图执行forward转发操作
    return "show";

}

当然,也可以直接返回资源的物理视图名。不过,此时就不需要再在视图解析器中再配置前辍与后辍了。

2.3.3 返回 void

对于处理器方法返回 void 的应用场景,AJAX 响应. 若处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void。

不能表示数据,也不能表示视图。

在处理ajax的时候,可以使用void返回值。通过HttpServletResponse输出数据,响应ajax请求。ajax请求服务器端返回的就是数据,和视图无关。

//处理器方法返回void,响应ajax请求
@RequestMapping(value = "/returnVoid-ajax.do")
public void doReturnVoidAjax(HttpServletResponse response, String name, Integer age) throws IOException {
    System.out.println("===doReturnVoidAjax,name="+name+"age="+age);
    //处理ajax,使用json做数据的格式
    //service调用完成了使用student表示处理结果
    Student student =new Student();
    student.setName(name);
    student.setAge(age);

    String json ="";
    //把结果的对象转为json格式的数据
    if (student != null){
        ObjectMapper om= new ObjectMapper();
        json = om.writeValueAsString(student);
        System.out.println("student转化的json"+json);
    }
    //输出数据,响应ajax的请求
    response.setContentType("application/json;charset=utf-8");
    PrintWriter pw =response.getWriter();
    pw.println(json);
    pw.flush();
    pw.close();
}
2.3.4 返回对象 Object

处理器方法也可以返回 Object 对象。这个 Object 可以是 Integer,String,自定义对象, Map,List 等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。

返回对象,需要使用@ResponseBody 注解,将转换后的 JSON 数据放入到响应体中。

Object :例如string ,Integer, Map, List, student等 等都是对象,对象有属性,属性就是数据。 所以返回object表示数据,和视图无关。可以使用对象表示的数据,响应ajax请求。


现在做ajax,主要使用json的数据格式。实现步骤 :

  1. 加入处理json的工具库的依赖,springmvc默认使用的jackson。

  2. 在sprigmvc配置文件之间加入<mvc:annotation-driven>注解驱动。(把java对象转换成json)

    相当于:json=om. writeValueAsstring(student);

  3. 在处理器方法的上面加入@ResponseBody注解

    相当于:

    response. setContentType(" application/ json; charset=utf-8" );
    PrintWriter pw = response.getWriter();
    pw. println(json);

内部原理(了解):

springmvc处理器方法返回Object,可以转为json输出到浏览器,响应ajax的内部原理
1.<mvc:annotation-driven>注解驱动。
注解驱动实现的功能是 完成java对象到json,xml,text,二进制等数据格式的转换。

<mvc:annotation-driven>在加入到springmvc配置文件后,会自动创建HttpMessageConverter接口的7个实现类对象,包括MappingJackson2HttpMessageConverter ( 使用jackson工具库中的objec tMapper实现java对象转为json字符串 )

HttpMessageConverter接口:消息转换器
功能:定义了java转为json,xml等数据格式的方法。这个接口有很多的实现类。
这些实现类完成java对象到json , java对象到xml,java对象到二进制数据的转换

HttpMessageConverter 接口实现类(常用)作用
StringHttpMessageConverter负责读取字符串格式的数据和写出字符串格 式的数据
MappingJackson2HttpMessageConverter负责读取和写入 json 格式的数据。利用 Jackson 的 ObjectMapper 读写 json 数据,操作 Object 类型数据,可读取 application/json,响应媒体类型为 application/json

没有加入注解驱动<mvc:annotation-driven>标签时的状态
org.springframework.http.converter.ByteArrayHttpMessageConverter
org.springframework.http.converter.StringHttpMessageConverter
org.springframework.http.converter.xml.SourceHttpMessageConverter
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter

加入注解驱动<mvc:annotation-driven>标签时的状态
org.springframework.http.converter.ByteArrayHttpMessageConverter
org.springframework.http.converter.StringHttpMessageConverter
org.springframework.http.converter.ResourceHttpMessageConverter
org.springframework.http.converter.ResourceRegionHttpMessageConverter
org.springframework.http.converter.xml.SourceHttpMessageConverter
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter

下面的两个方法是控制器类把结果输出给浏览器时使用的:
boolean canwrite(Class<?> var1, @Nullable MediaType var2);
void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3)
例如处理器方法
@RequestMapping(value = " /returnString .do" )
public student doReturnView2 (Ht tpServletRequest request , string name, Integer age){
student student = new student();
student . setName( "lisi" );
student . setAge(20);
return student ;
}
  1. canWrite

作用检查处理器方法的返回值, 能不能转为var2表示的数据格式。检查student(lisi , 20)能不能转为var2表示的数据格式。如果检查能转为json,canwrite返回true
MediaType :表示数格式的,例如json ,xml等等

  1. write :

把处理器方法的返回值对象,调用jackson中的ObjectMapper转为json字符串。
json = om.writeValueAsString(student);

  1. @ResponseBody注解
    放在处理器方法的上面,通过HttpServletResponse输出数据,响应ajax请求的。

     PrintWriter pw = response.getWriter();
         pw.println(json);
         pw.flush();
         pw.close();
    
/**
 * 处理器方法返回一个student,通过框架转为json,响应ajax请求
 * @ResponseBody:
 * 作用:把处理器方法返回对象转为json后,通过HttpServletResponse 输出给浏览器。
 * 位置:方法的定义上面。和其它注解没有顺序的关系。
 返回对象框架的处理流程:

1. 框架会把返回student类型,调用框架的中ArrayList<HttpMessageConverter>中每个类的canWrite()方法
   检查那个HttpMessageConverter接口的实现类能处理Student类型的数据-MappingJackson2HttpMessageConverter
2. 框架会调用实现类的write ( ),MappingJackson2HttpMessageConverter的write()方法
   把李四同学的s tudent对象转为json,调用Jackson的objectMapper实现转为json
   contentType: appl icat ion/ json;charset=utf-8
3. 框架会调用ResponseBody把2的结果数据输出到浏览器,ajax 请求处理完成
 */
@RequestMapping(value = "/returnStudentJson.do")
@ResponseBody
public Student doStudentJsonObject(String name, Integer age) {
    //调用service ,获取请 求结果数据,Student对象表示结果数据
    Student student =new Student();
    student.setName("张三");
    student.setAge(20);
    return student;// 会被框架转为json
}

若要返回非中文字符串,将前面返回数值型数据的返回值直接修改为字符串即可。但若 返 回 的 字 符 串 中 带 有 中 文 字 符 , 则 接 收 方 页 面 将 会 出 现 乱 码 。 此 时 需 要 使 用

@RequestMapping 的 produces 属性指定字符集。

produces,产品,结果,即该属性用于设置输出结果类型。

在这里插入图片描述

2.4 解读<url-pattern/>
2.4.1 配置详解
  1. *.do

在没有特殊要求的情况下,SpringMVC 的中央调度器 DispatcherServlet 的常使用后辍匹配方式,如写为*.do 或者 *.action, *.mvc 等。

  1. /

可以写为/,因为 DispatcherServlet 会将向静态资源的获取请求,例如.css、.js、.jpg、.png 等资源的获取请求,**当作是一个普通的 Controller 请求。**中央调度器会调用处理器映射器为其查找相应的处理器。当然也是找不到的,所以在这种情况下,所有的静态资源获取请求也均会报 404 错误。


发起的请求是由哪些服务器程序处理的。

http://localhost:8080/ch05_url_pattern/index.jsp :tomcat(jsp会转为servlet)
http://localhost:8080/ch05_url_pattern/js/jquery-3.4.1.js : tomcat
http://localhost:8080/ch05_url_pattern/images/p1.jpg : tomcat
http://localhost:8080/ch05_url_pattern/html/test.html: tomcat
http://localhost:8080/ch05_url_pattern/some.do : DispatcherServlet(springmvc框架处理的)

tomcat本身能处理静态资源的访问, 像html, 图片, js文件都是静态资源

tomcat的web.xml文件有一个servlet 名称是 default , 在服务器启动时创建的。

<servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

default这个servlet作用:
The default servlet for all web applications, that serves static resources. It processes all requests that are not mapped to other servlets with servlet mappings (defined either here or in your own web.xml file).

1.处理静态资源
2.处理未映射到其它servlet的请求。

  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/</url-pattern>  表示静态资源和未映射的请求都这个default处理
</servlet-mapping>

使用斜杠"/"
当你的项目中使用了/, 它会替代tomcat中的default。
导致所有的静态资源都给DispatcherServlet处理,默认情况下DispatcherServlet没有处理静态资源的能力。
没有控制器对象能处理静态资源的访问。所以静态资源(html,js,图片,css)都是404.

2.4.2 静态资源访问

<url-pattern/>的值并不是说写为 / 后,静态资源就无法访问了。经过一些配置后,该问 题也是可以解决的。

  1. 在springmvc配置文件加入 <mvc:default-servlet-handler>

原理是:加入这个标签后, 框架会创健控制器对象DefaultServletHttpRequestHandler(类似我们自己创建的MyController)

DefaultServletHttpRequestHandler这个对象可以把接收的请求转发给tomcat的default这个servlet。在 Tomcat 中,有一个专门用于处理静态资源访问的 Servlet 名叫 DefaultServlet。其<servlet-name/>为 default。可以处理各种静态资源访问请求。该 Servlet 注册在 Tomcat 服务 器的 web.xml 中。在 Tomcat 安装目录/conf/web.xml。

default- servlet- handler和@RequestMapping注解有冲突,需要加入annotation-driven解决问题

  1. <mvc:resources/>使用(掌握)

在 Spring3.0 版本后,Spring 定义了专门用于处理静态资源访问请求的处理器 ResourceHttpRequestHandler,让这个对象处理静态资源的访问,不依赖tomcat服务器。。并且添加了标签,专门用于解决静态资源无法访问问题。

需要在 springmvc 配置文件中添加如下形式的配置:

在这里插入图片描述

mapping 表示对该资源的请求 ( 以 /images/ 开始的请求 , 如 /image/beauty.jpg , /images/car.png 等)。注意,后面是两个星号。

location 表示静态资源所在目录。当然,目录不要使用/WEB-INF/及其子目录。

mvc :resources和@RequestMapping有一定的冲突
加注解驱动:<mvc:annotation-driven />

使用一个配置语句,指定多种静态资源的访问:把静态资源文件放在static目录中


3. SSM 整合开发

SSM 编程,即 SpringMVC + Spring + MyBatis 整合(springMVC对应界面层,spring对应service层,MyBatis对应dao层),是当前最为流行的 JavaEE 开发技术架构。其实 SSM 整合的实质,仅仅就是将 MyBatis整合入 Spring。因为 SpringMVC原本就是 Spring 的一部分,不用专门整合。

SSM 整合的实现方式可分为两种:基于 XML 配置方式,基于注解方式。


4. SpringMVC 核心技术

4.1 请求重定向和转发

当处理器对请求处理完毕后,向其它资源进行跳转时,有两种跳转方式:请求转发与重定向。而根据所要跳转的资源类型,又可分为两类:跳转到页面与跳转到其它处理器。

注意,对于请求转发的页面,可以是WEB-INF中页面;而重定向的页面,是不能为WEB-INF 中页的。因为重定向相当于用户再次发出一次请求,而用户是不能直接访问 WEB-INF 中资源的。

SpringMVC 框架把原来 Servlet 中的请求转发和重定向操作进行了封装。现在可以使用简 单的方式实现转发和重定向。

forward:表示转发,实现 request.getRequestDispatcher("xx.jsp").forward() 
redirect:表示重定向,实现 response.sendRedirect("xxx.jsp")

forward :表示转发
redirect :表示重定向
forward和redirect都是关键字,有一个共同的特点---------不和视图解析器一同工作

4.1.1 请求转发

处理器方法返回 ModelAndView 时,需在 setViewName()指定的视图前添加 forward:,且此时的视图不再与视图解析器一同工作,这样可以在配置了解析器时指定不同位置的视图。 视图页面必须写出相对于项目根的路径。forward 操作不需要视图解析器。

处理器方法返回 String,在视图路径前面加入 forward: 视图完整路径。

语法: setViewName ( “forward:视图文件完整路径”)
forward特点:不和视图解析器 一同使用,就当项目中没有视图解析器

视图解析器:

<!--声明 springmvc框架中的视图解析器, 帮助开发人员设置视图文件的路径-->
<bean  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--前缀:视图文件的路径-->
    <property name="prefix" value="/WEB-INF/view/" />
    <!--后缀:视图文件的扩展名-->
    <property name="suffix" value=".jsp" />
</bean>
4.1.2 请求重定向

在处理器方法返回的视图字符串的前面添加 redirect:,则可实现重定向跳转。

处理器方法返回ModelAndView,实现重定向redirect
语法: setViewName( “redirect:视图完整路径”)
redirect特点:不和视图解析器一同使用, 就当项目中没有视图解析器

框架对重定向的操作:

  1. 框架会把Model中的简单类型的数据,转为string 使用,作为页面的get请求参数使用。
    目的是在两次请求之间传递数据
  2. 在目标页面可以使用参数集合对象${param }获取请求参数值
    ${ param . myname }
  3. 重定向不能访问/WEB- INF资源
4.2 异常处理

springmvc框架采用的是统一,全局的异常处理。
把controller中的所有异常处理都集中到一个地方。 采用的是aop的思想。把业务逻辑和异常处理代码分开。解耦合。

使用两个注解:

  1. @ExceptionHandler
  2. @ControllerAdvice
异常发生处理逻辑:
1.需要把异常记录下来,记录到数据库,日志文件。记录日志发生的时间,哪个方法发生的,异常错误内容。
2.发送通知,把异常的信息通过邮件,短信,微信发送给相关人员。
3.给用户友好的提示。
4.2.1 @ExceptionHandler 注解

使用注解@ExceptionHandler 可以将一个方法指定为异常处理方法。该注解只有一个可 选属性 value,为一个 Class数组,用于指定该注解的方法所要处理的异常类,即所要匹 配的异常。

而被注解的方法,其返回值可以是 ModelAndView、String,或 void,方法名随意,方法 参数可以是 Exception 及其子类对象、HttpServletRequest、HttpServletResponse 等。系统会 自动为这些方法参数赋值。

对于异常处理注解的用法,也可以直接将异常处理方法注解于 Controller 之中。

@ControllerAdvice :控制器增强给控制器类增加功能-----异常处理功能)
位置:在类的上面。
特点:必须让框架知道这个注解所在的包名,需要在springmvc配置文件声明组件扫描器。
指定@Control lerAdvice所在的包名

<context:component-scan base-package="com.bjpowernode.handler" />
<mvc:annotation-driven />

处理异常的方法和控制器方法的定义一样,可以有多个参数 ,可以有ModelAndView,string, void ,对象类型的返回值。

形参: Exception,表示Controller中抛出的异常对象。
通过形参可以获取发生的异常信息。

@ExceptionHandler(异常的class) :表示异常的类型,当发生此类型异常时,由当前方法处理

//例如:
@ControllerAdvice
public class GlobalExceptionHandler {
	@ExceptionHandler(value = NameException.class)
	public ModelAndView doNameException(Exception exception){
    ...
    }
}
4.3 拦截器

SpringMVC 中的 Interceptor 拦截器是非常重要和相当有用的,它的主要作用是:拦截指定的用户请求,并进行相应的预处理与后处理。其拦截的时间点在“处理器映射器根据用户提交的请求,映射出了所要执行的处理器类,并且也找到了要执行该处理器类的处理器适配器, 在处理器适配器执行处理器之前”。当然,在处理器映射器映射出所要执行的处理器类时, 已经将拦截器与处理器组合为了一个处理器执行链,并返回给了中央调度器。


拦截器:
1)拦截器是springmvc中的一种,需要实现HandlerInterceptor接口。
2)拦截器和过滤器类似,功能方向侧重点不同。 过滤器是用来过滤器请求参数,设置编码字符集等工作。
拦截器是拦截用户的请求,做请求做判断处理的。
3)拦截器是全局的,可以对多个Controller做拦截。
一个项目中可以有0个或多个拦截器, 他们在一起拦截用户的请求。
拦截器常用在:用户登录处理,权限检查, 记录日志。

  • 拦截器的使用步骤:
    1.定义类实现HandlerInterceptor接口
    2.在springmvc配置文件中,声明拦截器, 让框架知道拦截器的存在。

  • 拦截器的执行时间:
    1)在请求处理之前, 也就是controller类中的方法执行之前先被拦截。
    2)在控制器方法执行之后也会执行拦截器。
    3)在请求处理完成后也会执行拦截器。

拦截器:看做是多个Controller中公用的功能,集中到拦截器统一处理。使用的aop的思想


package com.bjpowernode.handler;

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

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

public class MyInterception implements HandlerInterceptor {

    /*
        preHandle叫做预处理方法。
        重要:是整个项目的入口,门户。当preHandle返回true请求可以被处理。

        参数:
        Object handler:被拦截的控制器对象
        返回值boolean
            true:请求是通过了拦截器的验证,可以执行处理器方法。
            false :请求没有通过拦截器的验证,请求到达拦截器就截止了。请求没有被处理
                拦截器的MyInterceptor的preHandle()


        特点:
            1.方法在控制器方法( MyController的doSome )之前先执行的。
            用户的请求首先到达此方法

            2.在这个方法中可以获取请求的信息, 验证请求是否符合要求。
            可以验证用户是否登录,验证用户 是否有权限访问某个连接地址( url )。
            如果验证失败,可以截断请求,请求 不能被处理。
            如果验证成功,可以放行请求, 此时控制器方法才能执行。

     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器的preHandle()");
        return false;
    }

    /*
    postHandle:后处理方法。
    参数:
        Object handler :被拦截的处理器对象MyController
        ModelAndView modelAndView:处理器方法的返回值
    特点:
    1.在处理器方法之后执行的( MyController. doSome() )
    2.能够获取到处理器方法的返回值ModelAndView,可以修改ModelAndView中的数据和视图,可以影响到最后的执行结果。
    3.主要是对原来的执行结果做二次修正,

     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器的postHandle()");


    }

    /*
    afterCompletion:最后执行的方法
    参数
        Object handler :被拦截器的处理器对象
        Exception ex :程序中发生的异常
    特点:
        1.在请求处理完成后执行的。框架中规定是当你的视图处理完成后,对视图执行了forward。就认为请求处理完成。
        2.一般做资源回收工作的,程序请求过程中创建了一些对象,在这里可以删除,把占用的内存回收。

     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {
        System.out.println("拦截器的afterCompletion()");
    }
}

拦截器中方法与处理器方法的执行顺序如下图:

在这里插入图片描述
在这里插入图片描述


多个拦截器:
第一个拦截器preHandle=true , 第二个拦截器preHandle=true

111111-拦截器的MyInterceptor的preHandle()
22222-拦截器的MyInterceptor的preHandle()
-----------执行MyController中的doSome方法====
22222-拦截器的MyInterceptor的postHandle()
111111-拦截器的MyInterceptor的postHandle()
22222-拦截器的MyInterceptor的afterCompletion()
111111-拦截器的MyInterceptor的afterCompletion()

在这里插入图片描述


在这里插入图片描述

第一个拦截器preHandle=true , 第二个拦截器preHandle=false

111111-拦截器的MyInterceptor的preHandle()
22222-拦截器的MyInterceptor的preHandle()
111111-拦截器的MyInterceptor的afterCompletion()


第一个拦截器preHandle=false , 第二个拦截器preHandle=true|false

111111-拦截器的MyInterceptor的preHandle()



**拦截器和过滤器的区别: **

  1. 过滤器是servlet中的对象, 拦截器是框架中的对象
  2. 过滤器实现Filter接口的对象, 拦截器是实现HandlerInterceptor
  3. 过滤器是用来设置request,response的参数,属性的,侧重对数据过滤的。拦截器是用来验证请求的,能截断请求。
  4. 过滤器是在拦截器之前先执行的。
  5. 过滤器是tomcat服务器创建的对象,拦截器是springmvc容器中创建的对象
  6. 过滤器是一个执行时间点。拦截器有三个执行时间点
  7. 过滤器可以处理jsp,js,html等等。
    拦截器是侧重拦截对Controller的对象。 如果你的请求不能被DispatcherServlet接收, 这个请求不会执行拦截器内容
  8. 拦截器拦截普通类方法执行,过滤器过滤servlet请求响应
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值