SpringMVC学习笔记

什么是SpringMVC

Spring MVC(全称 Spring Web MVC)是 Spring 框架提供的一款基于 MVC 模式的轻量级 Web 开发框架,是 Spring 为表示层(UI)开发提供的一整套完备的解决方案。

注:三层架构分为表示层(UI)、业务逻辑层(BLL)、数据访问层(DAL),表示层则包含前台页面和后台 Servlet,详情请参看《MVC 模式》一节。

Spring MVC 使用 MVC 架构模式的思想,将 Web 应用进行职责解构,把一个复杂的 Web 应用划分成模型(Model)、控制器(Contorller)以及视图(View)三层,有效地简化了 Web 应用的开发,降低了出错风险,同时也方便了开发人员之间的分工配合。

Spring MVC 各层的职责如下:
  • Model:负责对请求进行处理,并将结果返回给 Controller;
  • View:负责将请求的处理结果进行渲染,展示在客户端浏览器上;
  • Controller:是 Model 和 View 交互的纽带;主要负责接收用户请求,并调用 Model 对请求处理,然后将 Model 的处理结果传递给 View。


Spring MVC 本质是对 Servlet 的进一步封装,其最核心的组件是 DispatcherServlet,它是 Spring MVC 的前端控制器,主要负责对请求和响应的统一地处理和分发。Controller 接收到的请求其实就是 DispatcherServlet 根据一定的规则分发给它的。

Spring MVC 框架内部采用松耦合、可插拔的组件结构,具有高度可配置性,比起其他的 MVC 框架更具有扩展性和灵活性。此外,Spring MVC 的注解驱动(annotation-driven)和对 REST 风格的支持,也是它最具有特色的功能。 

Spring MVC 是 Spring 框架的众多子项目之一,自 Spring 框架诞生之日起就包含在 Spring 框架中了,它可以与 Spring 框架无缝集成,在性能方面具有先天的优越性。对于开发者来说,Spring MVC 的开发效率要明显高于其它的 Web 框架,因此 Spring MVC 在企业中得到了广泛的应用,成为目前业界最主流的 MVC 框架之一。

 SpringMVC执行原理

图为SpringMVC的一个较完整的流程图,实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线表示需要开发者实现。

简要分析执行流程

  1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。

    我们假设请求的url为 : http://localhost:8080/SpringMVC/hello

    如上url拆分成三部分:

    http://localhost:8080服务器域名

    SpringMVC部署在服务器上的web站点

    hello表示控制器

    通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。

  2. HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。

  3. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。

  4. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。

  5. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。

  6. Handler让具体的Controller执行。

  7. Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。

  8. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。

  9. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。

  10. 视图解析器将解析的逻辑视图名传给DispatcherServlet。

  11. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。

  12. 最终视图呈现给用户。

在maven项目中搭建SpringMVC环境

导入maven依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.22</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.7</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.23</version>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>

        <!--         https://mvnrepository.com/artifact/javax.servlet/jstl-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

 创建springMVC配置文件

路径

<?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
                           https://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/mvc
                           https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--自动扫描包下注解-->
    <!--会自动扫描该包下的所有注解,使注解生效-->
    <context:component-scan base-package="com.controller"/>
    <!--    让spring不使用视图解析器过滤静态资源  .css .js .html .mp3 .mp4-->
    <mvc:default-servlet-handler/>
    <!--    开启注解驱动 即开启处理器映射器,处理器适配器-->
    <mvc:annotation-driven/>

    <!--    视图处理器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>



</beans>

在web.xml中配置springMVC的DispatcherServlet和CharacterEncodingFilter

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

<!--        设置DispatcherServlet的contextConfigLocation参数-->
<!--        值为spring的配置文件路径-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:appcontextconfig.xml</param-value>
        </init-param>
<!--        设置该servlet的启动级别-->
<!--        1为服务器启动时启动-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>app1</servlet-name>
<!--        设置servlet的处理url-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
<!--  设置spring的字符过滤器-->
    <filter>
        <filter-name>fil1</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--        设置字符编码为utf-8-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
<!--    设置匹配路径-->
    <filter-mapping>
        <filter-name>fil1</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

servlet的 / 和 /*

相同点

绝大部分场景下具有相同的表现:匹配所有

不同点

就是由于它们的相同点(如此相似),所以才让我们难以区分。

关于/

  • servlet中特殊的匹配模式(用在Filter中无效),
  • 因为是缺省匹配代表匹配所有路径,所以只可能存在一个实例(若存在多个就覆盖)
  • 优先级最低(兜底),这是和/*的最大区别。它不会覆盖任何其它的url-pattern,只会覆盖Servlet容器(如Tomcat)内建的DefaultServlet

关于/*

  • 属于4中匹配模式中的路径匹配,可用于Servlet和Filter
  • 优先级很高(仅次于精确匹配)。所以它会覆盖所有的后缀名匹配,从而很容易引起404问题,所以这种模式的“伤害性”是非常强的,一般有且仅用在Filter上

 引用自Servlet中/和/*的区别详解_java_脚本之家 (jb51.net)

 注解开发springMVC

@Controller

该注解用于类上,在类上使用后,会将该类注册为一个控制器类,就可以在该类里面写方法进行于前端交互,并调用service层方法进行业务处理。

该类里面有一个参数为value,用于命名使用了该注解的类的bean的id,value默认为"" (空字符串,不是NULL),默认为”"的话,相应的bean的id会默认为该类名称加首字母小写。

@RequestMapping(value="")

该注解可用于类上和方法上,用于注册该控制器方法的url,其中value值就为url,必须以"/"开头,

例:该控制器类中的list方法访问url为 项目路径/books/listAll,

下面这个访问url就是 项目路径/listAll 

@RequestMapping中还有一个参数为method,该值取值范围为GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;用于指定访问url的类型,

        1 GET 请求指定的页面信息,并返回实体主体。

        2 HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头

        3 POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包              含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。

        4 PUT 从客户端向服务器传送的数据取代指定的文档的内容。

        5 DELETE 请求服务器删除指定的页面

        6 OPTIONS 允许客户端查看服务器的性能。

        7 TRACE 回显服务器收到的请求,主要用于测试或诊断。

        8 PATCH 实体中包含一个表,表中说明与该URI所表示的原内容的区别

 get的参数都在url中可以看到,post的参数在请求头的body中,可用抓包工具(fiddler等)查看

于@RequestMapping相似的还有@GetMapping,@PostMapping,@PutMapping,@DeleteMapping,@PatchMapping,这些注解只能用于方法上,都是对@RequestMapping的封装,指定了相应的method的值。

控制器方法的参数

控制器方法中的参数类型和数量是可变的,可任意设置。参数类型可以总结为:接收前端参数+向前端传参,可根据需要选择添加HttpServletRequest,和HttpServletResponse

接受前端参数:String类型,参数名必须于前端传来参数的name值完全一样,这样该方法里的值就是前端传来的相应的参数; 实体类类型,该实体类里面必须有set,get方法和有参无参构造函数,这样与该类里面参数完全相同的前端name对应的参数就被自动映射到实体类里面。

向前端传参:参数为Model接口类型,

 使用该接口的addAttribute方法可以向前端一键值对形式传递参数,第一光参数为key,第二个参数为值。

 RestFul风格

    引用自狂神说SpringMVC03:RestFul和控制器 (qq.com)

概念

        Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基          于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

功能

        资源:互联网所有的事物都可以被抽象为资源

        资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。

        分别对应 添加、 删除、修改、查询。

传统方式操作资源  :通过不同的参数来实现不同的效果!方法单一,post 和 get

        http://127.0.0.1/item/queryItem.action?id=1 查询,GET

        http://127.0.0.1/item/saveItem.action 新增,POST

        http://127.0.0.1/item/updateItem.action 更新,POST

        http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST

使用RESTful操作资源 :可以通过不同的请求方式来实现不同的效果!如下:请求地址一              样,但是功能可以不同!

        http://127.0.0.1/item/1 查询,GET

        http://127.0.0.1/item 新增,POST

        http://127.0.0.1/item 更新,PUT

        http://127.0.0.1/item/1 删除,DELETE

学习测试

  1. 在新建一个类 RestFulController

    @Controller
    public class RestFulController {
    }
  2. 在Spring MVC中可以使用  @PathVariable 注解,让方法参数的值对应绑定到一个URI模板变量上。

    @Controller
    public class RestFulController {
    
       //映射访问路径
       @RequestMapping("/commit/{p1}/{p2}")
       public String index(@PathVariable int p1, @PathVariable int p2, Model model){
           
           int result = p1+p2;
           //Spring MVC会自动实例化一个Model对象用于向视图中传值
           model.addAttribute("msg", "结果:"+result);
           //返回视图位置
           return "test";
           
      }
       
    }

  3. 我们来测试请求查看下

  4. 思考:使用路径变量的好处?

    • 使路径变得更加简洁;

    • 获得参数更加方便,框架会自动进行类型转换。

    • 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这里访问是的路径是/commit/1/a,则路径与方法不匹配,而不会是参数转换失败。

  5. 我们来修改下对应的参数类型,再次测试

    //映射访问路径
    @RequestMapping("/commit/{p1}/{p2}")
    public String index(@PathVariable int p1, @PathVariable String p2, Model model){
    
       String result = p1+p2;
       //Spring MVC会自动实例化一个Model对象用于向视图中传值
       model.addAttribute("msg", "结果:"+result);
       //返回视图位置
       return "test";
    
    }

 控制器方法的返回类型

返回类型可以为字符串和void

void,该方法不返回任何数值,在前端调用时页面不会刷新

string,与视图解析器混合使用:

 会进行字符串拼接,然后对拼接后的路径进行转发

加forward:前缀,冒号后面必须书写完整路径(项目资源路径或者注册的url路径都可以),转发到相应的位置显示,如

 该控制器方法会转发/WEB-INF/html目录下ajexText.html文件显示页面

加redirect:前缀,会重定向到相应的路径显示,如

 该控制器方法会重定向到/goLogin请求

@RestController,该注解的参数与@Controller一样,但是使用了该注解的类,里面的方法返回不会走视图解析器,会直接返回该方法返回的值到前端页面。

 json

json是前后端传参常用的一种数据类型,json的本质是一个字符串,格式为{"key":"值","":""},括号里面是键值对的格式。如下

 

后端常用的json包有两个:Jackson和Fastjson

都需要使用maven导包

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>

使用Jackson需要在控制器方法里面new一个ObjeckMapper类,利用ObjeckMapper类中的writeValueAsString()方法将对象转换为json字符串,参数为基本数据类型的话key值为参数名,为实体类(必须有get,set,有参无参构造方法)的话key为实体类的每个参数的参数名。

使用fastjson可以在控制器方法中直接使用JSON.toJSONString()方法进行转化字符串。

拦截器

拦截器值Spring AOP思想的一个实际应用,配置了拦截器后,在每一个url请求的控制方法执行时,都会使用拦截器中的方法选择时间执行

自己配置拦截器需要写一个类并继承HandlerInterceptor接口,接口里面的方法不是必须实现的,可选择实现

package com.config;

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

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

public class MyInterceptor implements HandlerInterceptor {
    
//    return true;放行,会执行下一个拦截器
//    return false;不会执行下一个拦截器,拒绝请求
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("===============处理前=================");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("===============处理后=================");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("===============清理=================");
    }
}

 在x写好类后还需要在spring配置文件中进行配置

<!--    配置mvc拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
<!--            /**表示拦截所有url-->
            <mvc:mapping path="/**"/>  
            <bean class="com.config.MyInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值