SpringMVC详解

6 篇文章 2 订阅

目录

一、SpringMVC的基本概念

(一)三层架构和MVC

1、三层架构概述

2、model1模式介绍

3、model2模式介绍

4、MVC模式介绍

(二)SpringMVC概述

1、SpringMVC是什么?

2、SpringMVC在三层架构中的位置

3、SpringMVC主要组件

二、SpringMVC入门

(一)SpringMVC的入门案例

1、入门案例需求分析

2、构建maven项目并添加依赖

3、web.xml中配置核心控制器DispatcherServlet

4、配置SpringMVC

5、构建页面发起请求

6、编写控制器并注解配置

7、启动服务器测试

(二)SpringMVC执行过程及原理分析

1、案例的执行过程

2、SpringMVC的请求响应流程

(三)SpringMVC常用组件介绍

1、DispatcherServlet:前端控制器

2、HandlerMapping:处理器映射器

3、Handler:处理器

4、HandlerAdapter:处理器适配器

5、View Resolver:视图解析器

6、View:视图

7、mvc:annotation-driven标签说明

(四)RequestMapping注解

1、RequestMapping注解源码解读

2、RequestMapping注解的描述

(1)注解位置

(2)注解属性

三、SpringMVC中的请求参数绑定

(一)绑定说明

1、绑定的机制

2、支持的数据类型

3、使用要求

(二)参数绑定示例

1、基本类型和string作为参数

(1)页面定义请求

(2)执行器方法绑定参数

2、POJO类型作为参数

(1)页面定义请求

(2)执行器方法绑定参数

3、POJO类中包含集合类型参数

(1)页面定义请求

(2)执行器方法绑定参数

4、数组类型参数

(1)页面定义请求

(2)执行器方法绑定参数

5、使用ServletAPI对象作为方法参数

(1)引用ServletAPI的依赖jar包

(2)执行器方法绑定参数

6、请求参数乱码问题

(1)Get请求的编码问题,要改tomcat的server.xml配置文件

(2)POST请求的编码问题,要在web.xml文件中配置编码过滤器

7、静态资源访问

(1)将静态资源交给默认的DefaultServlet处理

(2)指定静态资源的访问路径

(三)自定义参数处理

1、使用场景

2、使用步骤

(1)定义类型转换器

(2)配置类型转换器

(3)引用类型转换器

四、SpringMVC的注解详解

(一)RequestParam

1、注解介绍

2、注解使用案例

(二)RequestHeader

1、注解介绍

2、注解使用案例

(三)RequestBody

1、注解介绍

2、注解使用案例

(1)直接获取请求体内容

(2)将json格式请求参数绑定到指定对象bean中

(四)CookieValue

1、注解介绍

2、注解使用案例

(五)ModelAttribute

1、注解介绍

2、注解使用案例

(1)注解在方法上

(2)注解在参数位置

五、Rest风格编程

(一)Rest风格URL规范介绍

1、什么是restful

2、restful的优点

3、restful的特性

(1)资源(Resource)

(2)表现层(Representation)

(3)状态转化(State Transfer)

(4)传统请求URL

(5)REST风格请求

(二)PathVariable注解详解

(三)PathVariable案例

1、构建页面发起请求

2、定义控制层执行器处理请求

3、引入请求方式转换过滤器

六、响应数据和结果视图

(一)返回值分类

1、返回值为字符串

2、void类型

3、ModelAndView

(二)转发和重定向

1、forward请求转发

2、redirect重定向

七、Postman工具使用

(一)介绍

(二)下载安装

1、下载地址:https://www.postman.com/downloads/

(三)工具的使用

八、SpringMVC中的父子容器解析

九、SpringMVC中的文件上传

(一)文件上传的必要前提

(二)原理分析

(三)SpringMVC的文件上传

1、构建工程添加相关依赖

2、编写jsp页面

3、编写控制器

4、配置文件解析器

十、SpringMVC中的异常处理

(一)异常处理的方式介绍

(二)异常处理的设计思路

(三)异常处理的步骤

1、编写异常类和错误页面

2、自定义异常处理器

3、配置异常处理器

十一、SpringMVC中的拦截器使用

(一)拦截器的介绍和作用

(二)拦截器与过滤器的区别

(三)自定义拦截器的步骤

1、实现HandlerInterceptor接口

2、配置拦截器

(四)拦截器的注意事项

1、拦截器的放行

2、拦截器中方法的说明

preHandle()方法:

postHandle()方法

afterCompletion()方法

3、拦截器的作用路径

4、多个拦截器的执行顺序

十二、拦截器的简单案例

(一)实现思路分析

(二)案例代码

1、登录页面login.jsp定义

2、控制器实现

3、拦截器实现

4、注册拦截器


一、SpringMVC的基本概念

(一)三层架构和MVC

1、三层架构概述

开发架构一般都是基于两种形式:

  • C/S架构:客户端/服务器
  • B/S架构:浏览器/服务器

在javaEE开发中,几乎都是基于B/S架构的开发。那么在B/S架构中,系统标准的三层架构包括:表现层、业务层、持久层

  • 表现层:也就是我们常说的web层。他负责接受客户端请求,向客户端响应结果,通常客户端使用http协议请求web层,web需要接受http请求,完成http响应。
  • 业务层:也就是我们常说的service层。他负责业务逻辑处理。
  • 持久层:dao层。负责数据持久化,和数据库做交互。

2、model1模式介绍

这个模式十分简单,页面显示,控制分发,业务逻辑,数据访问全部通过JSP去实现。

优点:架构简单,比较适合小型项目开发

缺点:JSP职责不单一,职责过重,不便于维护 

3、model2模式介绍

这个模式通过两部分去实现,即JSP与Servlet。JSP负责控制分发,业务逻辑以及数据访问。

优点:职责清晰,较适合于大型项目架构

缺点: 不适合小型项目开发

4、MVC模式介绍

MVC模式则分为三大块,即视图(View),控制器(Control),模型(Model)。视图是JSP负责的页面显示,控制器则是Servlet负责的控制分发,模型包括Service和Dao两个部分,分别负责业务逻辑和数据访问。

 优点:分工明确,各司其职,互不干扰。适用于大型项目架构,有利于组件的重构

 缺点:增加了系统开发的复杂度

(二)SpringMVC概述

1、SpringMVC是什么?

SpringMVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分。简化开发,减少出错,方便组内开发人员之间的配合。

他通过一套注解,让一个简单的Java类成为处理请求的控制器,而无需实现任何接口。同时它还支持Restful编程风格的请求。

2、SpringMVC在三层架构中的位置

SpringMVC位于三层架构中的表现层,作用是接收请求响应数据,响应的数据通过视图、模版展示给用户。

 

3、SpringMVC主要组件

  • 前端控制器(DispatcherServlet):接收请求、响应结果,相当于转发器,有了DispatcherServlet就减少了其他组件之间的耦合度。
  • 处理器映射器(HandlerMapping):根据请求的URL来查找Handler
  • 处理器适配器(HandlerAdapter):负责执行Handler
  • 处理器(Handler):处理业务逻辑的Java类
  • 视图解析器(ViewResolver):进行视图的解析,根据视图逻辑名将ModelAndView解析成真正的视图。
  • 视图(View):View是一个接口,他的实现类支持不同的视图类型,如jsp,freemarker等等。

二、SpringMVC入门

(一)SpringMVC的入门案例

1、入门案例需求分析

构建页面index.jsp发起请求,在服务器端处理请求,控制台打印处理请求成功,跳转main.jsp成功页面。

2、构建maven项目并添加依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.1.7.RELEASE</version>
</dependency>

3、web.xml中配置核心控制器DispatcherServlet

<servlet>
    <servlet-name>springmvc01</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>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc01</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

4、配置SpringMVC

<!--扫描注解包-->
<context:component-scan base-package="com.offcn.controller">
</context:component-scan>

<!--处理器映射器:根据请求路径匹配映射路径找到对应的执行器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>

<!--处理器适配器:根据处理器映射器返回的执行器对象,去执行执行器对象-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>

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

5、构建页面发起请求

<a href="/hello/test1">hello</a>

6、编写控制器并注解配置

@Controller
@RequestMapping("hello")
public class HelloController {
    @RequestMapping("test1")
    public String test1(){
        System.out.println("正在处理请求");
        return "main";
    }
}

7、启动服务器测试

pom.xml文件中服务器插件配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <!--指定编码格式-->
                <uriEncoding>utf-8</uriEncoding>
                <!--指定项目启动后的访问路径-->
                <path>/</path>
                <!--指定访问端口号-->
                <port>8888</port>
            </configuration>
        </plugin>
    </plugins>
</build>

(二)SpringMVC执行过程及原理分析

1、案例的执行过程

浏览器客户端发起请求,请求到达服务器tomcat,tomcat将请求相关信息参数封装到对象request和response中,再将request和response对象交给Service方法处理,在Service方法中会根据请求路径将请求交给对应的Controller执行器处理。

 

2、SpringMVC的请求响应流程

浏览器发送请求,被DispatcherServlet捕获,DispatcherServlet没有直接处理请求,而是将请求交给HandlerMapping处理器映射器,处理器映射器根据请求路径去Controller控制层中匹配对应的执行器,并将匹配结果返回给DispatcherServlet,由DispatcherServlet调用HandlerAdapter处理器适配器来执行控制层执行器方法;

执行器方法执行后的返回结果,由DispatcherServlet交给视图解析器ViewResolver来处理,找到对应的结果视图,渲染视图,并将结果响应给浏览器。

 

(三)SpringMVC常用组件介绍

1、DispatcherServlet:前端控制器

用户请求到达前端控制器,他就相当于mvc模式中的C,DispatcherServlet是整个流程控制的中心,由它调用其他组件处理用户的请求,DispatcherServlet的存在降低了组件之间的耦合性。

2、HandlerMapping:处理器映射器

HandlerMapping负责根据用户请求找到Handler,即处理器,SpringMVC提供了不同的映射器实现不同的映射方式。例如:配置文件方式,实现接口方式,注解方式。

3、Handler:处理器

它就是我们开发中要编写的具体业务控制器。由DispatcherServlet把用户请求转发到Handler。由Handler对具体的用户请求进行处理。

4、HandlerAdapter:处理器适配器

通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。

5、View Resolver:视图解析器

ViewResolver负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。

6、View:视图

SpringMVC框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。

7、mvc:annotation-driven标签说明

在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器称为SpringMVC的三大组件。

使用<mvc:annotation-driven>自动加载RequestMappingHandlerMapping(处理器映射器)和RequestMappingHandlerAdapter(处理器适配器),可用在SpringMVC.xml配置文件中使用<mvc:annotation-driven>替代处理器映射器和适配器的配置。

<mvc:annotation-driven>标签相当于以下配置:

<!-- HandlerMapping处理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
</bean>

<!-- HandlerAdapter处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
erAdapter"></bean>
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter">
</bean>
<bean
class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">
</bean>

<!-- HadnlerExceptionResolvers异常处理器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolv
er"></bean>
<bean
class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver"></bean>

(四)RequestMapping注解

用于定义映射路径,建立请求url和控制层方法之间的对应关系

1、RequestMapping注解源码解读

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
    public @interface RequestMapping {
        String name() default "";
        @AliasFor("path")
        String[] value() default {};
        @AliasFor("value")
        String[] path() default {};
        RequestMethod[] method() default {};
        String[] params() default {};
        String[] headers() default {};
}

2、RequestMapping注解的描述

(1)注解位置
  • 类上:定义一级映射路径
  • 方法上:定义二级映射路径

(2)注解属性
  • value:用于指定映射路径url。他和path属性的作用是一样的。
  • method:用于指定请求的方式。
  • params:用于指定限制请求参数的条件。它支持简单的表达式。
    要求请求参数的 key 和 value 必须和配置的一模一样
  • headers:用于指定限制请求消息头的条件。

三、SpringMVC中的请求参数绑定

(一)绑定说明

1、绑定的机制

表单中请求参数都是基于key=value的。SpringMVC绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的。

2、支持的数据类型

基本类型参数:包括基本类型和String

POJO类型参数:包括实体类,以及关联的实体类

数组和集合类型参数:包括List结构和Map结构的集合。

3、使用要求

基本类型或者String类型:要求我们的参数名称必须和控制器中方法的形参名称保持一致。

POJO类型:要求表单中参数名称和POJO类的属性名称保持一致。并且控制器方法的参数类型是POJO类型。

集合类型

        第一种:要求集合类型的请求参数必须在POJO中。在表单中请求参数名称要和POJO中集合属性名称相同。给List集合中的元素赋值,使用下标。给Map集合中的元素赋值,使用键值对。

        第二种:接收的请求参数是json格式数据。需要借助一个注解实现。

(二)参数绑定示例

1、基本类型和string作为参数

(1)页面定义请求
<form action="/hello/test2" method="post">
    用户名:<input name="userName" type="text">
    年龄:<input name="age" type="text">
    <input type="submit" value="提交">
</form>
(2)执行器方法绑定参数
@RequestMapping("test2")
public String test2(String userName,int age){
    System.out.println("用户名:"+userName);
    System.out.println("年龄:"+age);
    return "main";
}

2、POJO类型作为参数

(1)页面定义请求
<form action="/hello/test3" >
    用户名:<input name="pname" type="text">
    年龄:<input name="age" type="text">
    车名称:<input name="car.cname" type="text">
    车价格:<input name="car.cprice" type="text">
    <input type="submit" value="提交">
</form>
(2)执行器方法绑定参数
@RequestMapping("test3")
public String test3(Person person){
    System.out.println(person);
    return "main";
}

3、POJO类中包含集合类型参数

(1)页面定义请求
<form action="/hello/test4" >
    用户名:<input name="pname" type="text">
    年龄:<input name="age" type="text">
    车名称:<input name="car.cname" type="text">
    车价格:<input name="car.cprice" type="text">
    list集合车1:车名称<input name="carList[0].cname" type="text">
    list集合车1:车价格<input name="carList[0].cprice" type="text">
    list集合车2:车名称<input name="carList[1].cname" type="text">
    list集合车2:车价格<input name="carList[1].cprice" type="text">
    set集合车1:车名称<input name="carSet[0].cname" type="text">
    set集合车1:车价格<input name="carSet[0].cprice" type="text">
    set集合车2:车名称<input name="carSet[1].cname" type="text">
    set集合车2:车价格<input name="carSet[1].cprice" type="text">
    map集合车1:车名称<input name="map['x']" type="text">
    map集合车1:车价格<input name="map['y']" type="text">
    map集合车2:车名称<input name="map['x2]" type="text">
    map集合车2:车价格<input name="map['y2']" type="text">
    <input type="submit" value="提交">
</form>
(2)执行器方法绑定参数
@RequestMapping("test4")
public String test4(Person person){
    System.out.println(person);
    return "main";
}

4、数组类型参数

(1)页面定义请求
<form action="/hello/test5" >
    爱好1:<input name="hobbies" type="text">
    爱好2:<input name="hobbies" type="text">
    爱好3:<input name="hobbies" type="text">
    <input type="submit" value="提交">
</form>
(2)执行器方法绑定参数
@RequestMapping("test5")
public String test5(String[] hobbies){
    for(String hobby:hobbies){
        System.out.println(hobby);
    }
    return "main";
}

5、使用ServletAPI对象作为方法参数

(1)引用ServletAPI的依赖jar包
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>
(2)执行器方法绑定参数
@RequestMapping("test6")
public void test6(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("我在请求转发");
    request.getRequestDispatcher("/hello/test1").forward(request,response);
}

6、请求参数乱码问题

(1)Get请求的编码问题,要改tomcat的server.xml配置文件
<Connector connectionTimeout="20000" port="8080"protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>
(2)POST请求的编码问题,要在web.xml文件中配置编码过滤器
<filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filterclass>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>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

7、静态资源访问

(1)将静态资源交给默认的DefaultServlet处理
        在springMVC.xml配置文件中加如下配置:
<mvc:default-servlet-handler></mvc:default-servlet-handler>
(2)指定静态资源的访问路径

        在springMVC.xml配置文件中加如下配置:

<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>

(三)自定义参数处理

1、使用场景

SpringMVC不能自动识别参数转换为我们需要的数据类型,浏览器报400错误,类型转换异常。

2、使用步骤

(1)定义类型转换器
public class MyDateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String source) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date=simpleDateFormat.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}
(2)配置类型转换器
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <bean class="com.offcn.util.MyDateConverter"></bean>
    </property>
</bean>
<mvc:annotation-driven conversion-service="conversionService"/>
(3)引用类型转换器
<form action="/hello/test7" >
    入职日期:<input name="hireDate" type="date">
    <input type="submit" value="提交">
</form>

@RequestMapping("test7")
public String test7(Date hireDate){
    System.out.println(hireDate);
    return "main";
}

四、SpringMVC的注解详解

(一)RequestParam

1、注解介绍

使用在方法入参位置,用于指定请求参数名称,将该请求参数绑定到注解参数位置

属性:name:指定要绑定的请求参数名称

           required:指定请求参数是否必传

           defaultValue:指定当没有传入请求参数时的默认取值

2、注解使用案例

@RequestMapping("test1")
public String test1(@RequestParam(name = "pname",required = true,defaultValue = "李四")String name){
    System.out.println(name);
    return "main";
}

(二)RequestHeader

1、注解介绍

注解在方法入参位置,用于获取请求头信息

2、注解使用案例

@RequestMapping("test2")
public String test2(@RequestHeader("Upgrade-Insecure-Requests")String data){
    System.out.println(data);
    return "main";
}

(三)RequestBody

1、注解介绍

用于方法入参位置,获取请求体内容。直接使用得到是key=value&key=value...结构的数据。get请求方式不适用。通常用于将json格式字符串绑定到bean对象中。

2、注解使用案例

(1)直接获取请求体内容
<form action="/annotation/test3" method="post">
    用户名:<input name="userName" type="text">
    年龄:<input name="age" type="text">
    <input type="submit" value="提交">
</form>


@RequestMapping("test3")
public String test3(@RequestBody String data){
    System.out.println(data);
    return "main";
}

(2)将json格式请求参数绑定到指定对象bean中

添加json转换配置:

添加一个json的转换依赖:(fastjson)

pom.xml:

<dependencies>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.70</version>
    </dependency>
</dependencies>

springMVC.xml,配置fastjson:

<!--开启springmvc注解-->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <!-- 配置Fastjson支持 -->
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=UTF-8</value>
                        <value>application/json</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

<button onclick="sendCar()">发起ajax请求</button>
<script>
    function sendCar() {
        $.ajax({
            type: "POST",
            url: "/annotation/test4",
            data: '{"cname":"宝马","cprice":"20"}',
            contentType:"application/json",
            success: function(msg){
                alert( "Data Saved: " + msg );
            }
        });
    }
</script>

@RequestMapping("test4")
public String test4(@RequestBody Car car){
    System.out.println(car);
    return "main";
}

(四)CookieValue

1、注解介绍

用于方法入参位置,把指定cookie名称的值传入控制器方法参数

2、注解使用案例

@RequestMapping("test5")
public String test5(@CookieValue("JSESSIONID") String data){
    System.out.println(data);
    return "main";
}

(五)ModelAttribute

1、注解介绍

该注解是SpringMVC4.3版本以后新加入的。它可以用于修饰方法和参数。

  • 出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。
  • 出现在参数上,获取指定的数据给参数赋值。

2、注解使用案例

(1)注解在方法上
@ModelAttribute("shareParam")
public String test6(){
    System.out.println("我是公共方法");
    return "公共参数";
}
(2)注解在参数位置
@RequestMapping("test7")
public String test7(@ModelAttribute("shareParam")String data){
    System.out.println(data);
    return "main";
}

五、Rest风格编程

(一)Rest风格URL规范介绍

1、什么是restful

Restful架构,就是目前最流行的一种互联网软件架构风格。REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。Fielding将他对互联网软件的架构原则,定名为REST,即Representational State Transfer的缩写。即"表现层状态转化"。如果一个架构符合REST原则,就称它为Restful架构。值得注意的是 REST并没有一个明确的标准,而更像是一种设计的格式。

它本身并没有什么实用性,其核心价值在于如何设计出符合 REST 风格的网络接口。

2、restful的优点

它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用

3、restful的特性

(1)资源(Resource)

网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个 URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要获取这个资源,访问它的 URI 就可以,因此 URI 即为每一个资源的独一无二 的识别符。

(2)表现层(Representation)

把资源具体呈现出来的形式,叫做它的表现层(Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。

(3)状态转化(State Transfer)

每发出一个请求,就代表了客户端和服务器的一次交互过程。

HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是“表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET 、POST 、PUT、 DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。

(4)传统请求URL

        新增:http://localhost:8888/annotation/addPerson POST

        修改:http://localhost:8888/annotation/updatePerson POST

        删除:http://localhost:8888/annotation/deletePerson?id=1 GET

        查询:http://localhost:8888/annotation/findPerson?id=1 GET

(5)REST风格请求

        新增:http://localhost:8888/annotation/person POST

        修改:http://localhost:8888/annotation/person PUT

        删除:http://localhost:8888/annotation/person/1 DELETE

        查询:http://localhost:8888/annotation/person/1 GET

(二)PathVariable注解详解

该注解用于绑定 url 中的占位符。例如:请求 url 中/annotation/test9/{id},这个{id}就是url占位符。url 支持占位符是 spring3.0 之后加入的。是springmvc 支持 rest 风格 URL 的一个重要标志。

属性:

          value:用于指定url中占位符名称

          required:是否必须提供占位符

(三)PathVariable案例

1、构建页面发起请求

REST风格编程:

新增:
<form action="/annotation/person" method="post">
    用户名:<input name="userName" type="text">
    年龄:<input name="age" type="text">
    <input type="submit" value="提交">
</form>

修改:
<form action="/annotation/person" method="post">
    <input type="hidden" name="_method" value="PUT">
    用户名:<input name="userName" type="text">
    年龄:<input name="age" type="text">
    <input type="submit" value="提交">
</form>

删除:
<form action="/annotation/person/1" method="post">
    <input type="hidden" name="_method" value="DELETE">
    <input type="submit" value="提交">
</form>

查询:
<a href="/annotation/person/1">查询用户</a>

2、定义控制层执行器处理请求

@RequestMapping(value = "person",method = RequestMethod.POST)
public String addPerson(String userName,int age){
    System.out.println("新增用户:"+userName);
    return "main";
}

@RequestMapping(value = "person",method = RequestMethod.PUT)
public String updatePerson(String userName,int age){
    System.out.println("修改用户:"+userName);
    return "main";
}

@RequestMapping(value = "person/{id}",method = RequestMethod.DELETE)
public String deletePerson(@PathVariable(value = "id")int id){
    System.out.println("删除用户:id"+id);
    return "main";
}

@RequestMapping(value = "person/{id}",method = RequestMethod.GET)
public String findPerson(@PathVariable(value = "id")int id){
    System.out.println("查询用户信息:id"+id);
    return "main";
}

3、引入请求方式转换过滤器

<filter>
    <filter-name>hiddenMethodFilter</filter-name>
    <filterclass>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>hiddenMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

六、响应数据和结果视图

(一)返回值分类

1、返回值为字符串

用于指定返回的逻辑视图名称

@RequestMapping("test1")
public String test1(String pname){
    System.out.println(pname);
    System.out.println("返回string类型测试");
    return "main";
}

2、void类型

通常使用原始servlet处理请求时,返回该类型

@RequestMapping("test2")
public void test2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("返回void类型测试");
    request.getRequestDispatcher("/response/test1").forward(request,response);
}

3、ModelAndView

用于绑定参数和指定返回视图名称

@RequestMapping("test3")
public ModelAndView test3(ModelAndView modelAndView){
    modelAndView.addObject("aa","aa1");
    modelAndView.setViewName("main");
    return modelAndView;
}

(二)转发和重定向

1、forward请求转发

@RequestMapping("test4")
public String test4(){
    System.out.println("我是请求转发");
    return "forward:/response/test1";
}

2、redirect重定向

@RequestMapping("test5")
public String test5(RedirectAttributes redirectAttributes,String pname){
    System.out.println("我是重定向");
    // redirectAttributes.addAttribute("pname",pname);
    redirectAttributes.addFlashAttribute("pname",pname);
    return "redirect:/response/test1";
}

注意:重定向携带参数,需要使用对象RedirectAttributes,该对象提供两个方法封装参数 addAttribute()和addFlashAttribute()。

第一个方法参数会明文显示在浏览器地址栏。

第二个方法参数会隐藏,使用第二种方法传参时,获取参数时需要加注解@ModelAttribute;

七、Postman工具使用

(一)介绍

用户在开发或者调试网络程序或者是网页B/S模式的程序的时候是需要一些方法来跟踪网页请求的,用户可以使用一些网络的监视工具比如著名的Firebug等网页调试工具。今天给大家介绍的这款网页调试工具不仅可以调试简单的css、html、脚本等简单的网页基本信息,它还可以发送几乎所有类型的HTTP请求!Postman在发送网络HTTP请求方面可以说是Chrome插件类产品中的代表产品之一。

(二)下载安装

1、下载地址:https://www.postman.com/downloads/

(三)工具的使用

 

八、SpringMVC中的父子容器解析

Spring和SpringMVC的容器具有父子关系,Spring容器为父容器,SpringMVC为子容器,子容器可以引用父容器中的bean,二父容器不可以引用子容器中的Bean。

  • 配置Spring的配置文件时,排除扫描控制层注解:
<context:component-scan base-package="com.offcn">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
  • 配置SpringMVC的配置文件时,扫描控制层注解:
<context:component-scan base-package="com.offcn.controller">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

九、SpringMVC中的文件上传

(一)文件上传的必要前提

  • form表单的enctype取值必须是:multipart/form-data(默认值是:application/x-www-form-urlencoded)enctype:是表单请求正文的类型。
  • method属性取值必须是Post
  • 提供一个文件选择域<input type="file"/>

(二)原理分析

当form表单的enctype取值不是默认值后,request。getParameter()将失效。

enctype="application/x-www-form-urlencoded"时,form表单的正文内容是:

key=value&key=value&key=value;

当form表单的enctype取值为Mutilpart/form-data时,请求正文内容就变成:每一部分都是MIME类型描述的正文。

(三)SpringMVC的文件上传

1、构建工程添加相关依赖

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

2、编写jsp页面

<form enctype="multipart/form-data" method="post" action="/file/fileUpload">
    <input type="file" name="file">
    <input type="submit" value="上传">
</form>

3、编写控制器

@RequestMapping("fileUpload")
public String fileUpload(MultipartFile file){
    File dest = new File("C:\\Users\\mwx\\Pictures\\"+file.getOriginalFilename());
    //文件上传
    try {
        file.transferTo(dest);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return "main";
}

4、配置文件解析器

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>

十、SpringMVC中的异常处理

(一)异常处理的方式介绍

系统中异常包括两类:预期异常和运行时异常RuntimeException。

前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发生。

(二)异常处理的设计思路

系统的dao、service、controller出现都通过throws Exception向上抛出,最后由SpringMVC前端控制器交由异常处理器进行异常处理。

(三)异常处理的步骤

1、编写异常类和错误页面

@RequestMapping("test2")
public String test2(){
    System.out.println("模拟出现异常");
    int i = 10/0;
    return "main";
}

2、自定义异常处理器

public class MyExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ex.printStackTrace();
        System.out.println("自定义异常处理");
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

3、配置异常处理器

<bean class="com.offcn.util.MyExceptionHandler"></bean>

十一、SpringMVC中的拦截器使用

(一)拦截器的介绍和作用

SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理后处理。用户可以自己定义一些拦截器来实现特定的功能。

拦截器链:就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

(二)拦截器与过滤器的区别

过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。拦截器是 SpringMVC 框架自己的,只有使用了SpringMVC框架的工程才能用。过滤器在web.xml中的 url-pattern 标签中配置了/*之后,可以对所有要访问的资源拦截。

我们要想自定义拦截器, 要求必须实现:HandlerInterceptor 接口。

(三)自定义拦截器的步骤

1、实现HandlerInterceptor接口

public class MyIntercepter implements HandlerInterceptor {
    /**
    * 控制层执行器方法前的拦截器
    * @param request
    * @param response
    * @param handler
    * @return
    * @throws Exception
    */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("我是控制层执行器方法前的拦截器");
        //校验用户是否登录
        HttpSession session = request.getSession();
        String pname=(String)session.getAttribute("pname");
        if(pname!=null){
            //当前用户已经登录,放行
            return true;
        }else{
            //当前用户未登录,拦截跳转到登录页面
            request.getRequestDispatcher("/login.jsp").forward(request,response);
            return false;
        }
        //返回true表示继续执行控制层执行器方法,返回false表示方法结束,不会执行控制层执行器方法
    }


    /**
    * 控制层方法返回时拦截器
    * @param request
    * @param response
    * @param handler
    * @param modelAndView
    * @throws Exception
    */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("我是控制层执行器方法返回时拦截器");
    }


    /**
    * 控制层方法结束后的拦截器
    * @param request
    * @param response
    * @param handler
    * @param ex
    * @throws Exception
    */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable Exception ex) throws Exception {
        System.out.println("我是控制层执行器方法结束后的拦截器");
    }
}

2、配置拦截器

<!--springMVC配置文件中注册拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/file/login"/>
        <bean class="com.offcn.util.MyIntercepter"></bean>
    </mvc:interceptor>
</mvc:interceptors>

(四)拦截器的注意事项

1、拦截器的放行

拦截器中的放行指的是:如果有下一个拦截器就执行下一个,如果该拦截器处于拦截器链的最后一个,则执行控制器中的方法。

2、拦截器中方法的说明

定义拦截器需要实现HandlerInterceptor接口,该接口中有三个方法:

  • preHandle()方法:

  控制层执行器方法前的拦截器(该方法时在控制层执行器方法前调用,当该方法返回结果为true则继续调用下一个拦截器,如果已经是最后一个拦截器,则调用控制层中的执行器方法;当该方法返回结果为false,则不会继续执行控制层执行器中的方法)

  • postHandle()方法

  控制层方法返回时拦截器(该方法是控制层执行器方法执行之后,由DispatcherServlet在将结果响应给浏览器前调用的方法)

  • afterCompletion()方法

  控制层方法结束后的拦截器(该方法在请求业务处理执行完全结束之后由DispatcherServlet调用执行)

public class MyInterceptor2 implements HandlerInterceptor {
    /**
    * 控制层执行器方法前的拦截器(该方法时在控制层执行器方法前调用,当该方法返回结果为true则继续调用下一个拦截器,如果已经时最后
    * 一个拦截器,则调用控制层中的执行器方法;当该方法返回结果为false,则不会继续执行控制层执行器中的方法)
    * @param request
    * @param response
    * @param handler
    * @return
    * @throws Exception
    */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("我是控制器方法前拦截器2");
        return true;
    }


    /**
    * 控制层方法返回时拦截器(该方法是控制层执行器方法执行之后,由DispatcherServlet在将结果响应给浏览器前调用的方法)
    * @param request
    * @param response
    * @param handler
    * @param modelAndView
    * @throws Exception
    */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable ModelAndView modelAndView) throws Exception{
        System.out.println("我是控制层执行器方法返回时拦截器2");
    }


    /**
    * 控制层方法结束后的拦截器(该方法在请求业务处理执行完全结束之后由DispatcherServlet调用执行)
    * @param request
    * @param response
    * @param handler
    * @param ex
    * @throws Exception
    */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable Exception ex) throws Exception {
        System.out.println("我是控制层执行器方法结束后的拦截器2");
    }
}

3、拦截器的作用路径

<!--拦截器注册-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/><!--用于指定拦截的 url-->
        <mvc:exclude-mapping path="/file/login"/><!--用于指定排除的 url-->
        <bean class="com.offcn.util.MyIntercepter"></bean>
    </mvc:interceptor>
</mvc:interceptors>

4、多个拦截器的执行顺序

(1) 先来顺序执行 所有拦截器的 preHandle方法

(2)如果任何一个拦截器返回false。直接跳出不执行目标方法

  •         如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle
  •         如果当前拦截器返回为false。直接 倒序执行所有已经执行了的拦截器的 afterCompletion;

(3)所有拦截器都返回True。执行目标方法

(4)倒序执行所有拦截器的postHandle方法。

(5)前面的步骤有任何异常都会直接倒序触发 afterCompletion

(6)页面成功渲染完成以后,也会倒序触发 afterCompletion

十二、拦截器的简单案例

(一)实现思路分析

1、定义登录页面,并定义请求映射。

2、判断用户名密码是否正确

3、如果正确 向 session 中写入用户信息

4、返回登录成功。

5、拦截用户请求,判断用户是否登录

6、如果用户已经登录。放行

7、如果用户未登录,跳转到登录页面

(二)案例代码

1、登录页面login.jsp定义

<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="/file/login" method="post">
    用户名:<input type="text" name="pname">
    密码:<input type="text" name="password">
    <input type="submit" value="登录">
</form>
</body>
</html>

2、控制器实现

@RequestMapping("login")
public String login(String pname, String password, HttpSession session){
    System.out.println("登录校验成功");
    //将登录成功的用户名存放到session中
    session.setAttribute("pname",pname);
    return "main";
}

3、拦截器实现

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println("我是控制层执行器方法前的拦截器");
    //校验用户是否登录
    HttpSession session = request.getSession();
    String pname=(String)session.getAttribute("pname");
    if(pname!=null){
        //当前用户已经登录,放行
        return true;
    }else{
        //当前用户未登录,拦截跳转到登录页面
        request.getRequestDispatcher("/login.jsp").forward(request,response);
        return false;
    }
    //返回true表示继续执行控制层执行器方法,返回false表示方法结束,不会执行控制层执行器方法
}

4、注册拦截器

<mvc:interceptor>
    <mvc:mapping path="/**"/><!--用于指定拦截的 url-->
    <mvc:exclude-mapping path="/file/login"/><!--用于指定排除的 url-->
    <bean class="com.offcn.util.MyIntercepter"></bean>
</mvc:interceptor>

  • 14
    点赞
  • 130
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

互联网底层民工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值