Spring MVC | Spring MVC 的“核心类” 和 “注解”

目录:

  • [Spring MVC 的"核心类" 和 "注解" :](#Spring MVC 的“核心类” 和 “注解” :)
    • 1.DispatcherServlet (前端控制器)
    • [2.@Controller 注解](#2.@Controller 注解)
    • [3.RequestMapping 注解](#3.RequestMapping 注解)
      • [3.1 @RequestMapping 注解的 "使用"](#3.1 @RequestMapping 注解的 “使用”)
        • [标注在 "方法" 上](#标注在 “方法” 上)
        • [标注在 "类" 上](#标注在 “类” 上)
      • [3.2 @RequestMapping 注解的 "属性"](#3.2 @RequestMapping 注解的 “属性”)
    • 4.组合注解
      • [4.1 请求处理方法的 "参数类型" 和 "返回值类型"](#4.1 请求处理方法的 “参数类型” 和 “返回值类型”)
        • [请求处理方法中的 "参数类型"](#请求处理方法中的 “参数类型”)
        • [请求处理方法的 "返回值类型"](#请求处理方法的 “返回值类型”)
          • [通过返回值"String类型"进行 "重定向"](#通过返回值“String类型”进行 “重定向”)
          • [通过返回值"String类型"进行 "请求forward转发"](#通过返回值“String类型”进行 “请求forward转发”)
    • 5.ViewResolver(视图解析器)

Spring MVC 的"核心类" 和 "注解" :

  • Spring 2.5之前只能使用实现Controller接口 的方式来开发一个控制器"SpringMVC的入门"例子的就是使用的此种方式。
  • Spring 2.5之后,新增加了基于注解的控制器 以及其他一些 常用注解 (即Spring2.5之后 ,可以通过注解操作Spring),这些注解 的使用极大地减少了程序员开发工作

1.DispatcherServlet (前端控制器)

  • DispatcherServlet全名org .springframework .web .servlet .DispatcherServlet,它在程序中充当着 前端控制器 的角色。 在使用时,只需将其配置项目的web.xml 文件 中。(在web.xml 中配置 "前端控制器")

  • web.xml 中 配置 DispatcherServlet (前端控制器 ) 的配置代码如下 :

    xml 复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
         <!--  在web.xml中配置"前端控制器" : DispatcherServlet -->
        <!--  配置"前端过滤器" : DispatcherServlet -->
        <!--  假如下面没有通过init-param元素来配置"springmvc配置的位置的话",应用程序会自动在web-inf目录下找名字为 : SpringMvc-servlet.xml的文件来充当"springmvc配置文件" (此处的名字和 DispatcherServlet的名称(SpringMvc)有关系) -->
        <servlet>
            <servlet-name>SpringMvc</servlet-name>
            <servlet-class>
                org.springframework.web.servlet.DispatcherServlet
            </servlet-class>
    
           <!--   初始化时加载SpringMVC的"配置文件" : springmvc-config.xml    -->
            <!--  如果配置"前端控制器"时,没有用<init-param>元素配置"Springmvc配置文件的位置",应用程序会到web-inf目录下找名字为: "servletName-servlet.xml" 的文件来充当 "springmvc配置文件"   -->
           <init-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>classpath:springmvc-config.xml</param-value>
           </init-param>
    
            <!--    表示容器启动时立刻加载此Servlet    -->
            <load-on-startup>1</load-on-startup>
        </servlet>
    
    
        <servlet-mapping>
            <servlet-name>SpringMvc</servlet-name>
            <!--  会将所有的url进行拦截  -->
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>

    上述代码 中,<load-on-startup>元素 和**<init-param>元素** 都是可选的。如果 <load-on-startup>元素值为 1,则在应用程序启动时会立即加载该Servlet;如果 <load-on-startup>元素不存在 ,则应用程序会第一个Servlet请求 时加载该Servlet 。 如果 <init-param>元素存在 并且通过其子元素 配置了 Spring MVC配置文件 ( Springmvc-config.xml )的路径 ,则应用程序在启动 时会加载配置路径下配置文件 ; 如果没有通过<init-param>元素 配置,则应用程序会默认WEB-INF目录下 寻找如下方式命名 ( servletName-servlet.xml )的配置文件

    java 复制代码
    //如果配置"前端控制器"时,没有用<init-param>元素配置"Springmvc配置文件的位置",应用程序会到web-inf目录下找名字为: "servletName-servlet.xml" 的文件来充当 "springmvc配置文件"
    //其中servletName的"泛指",指的是在web.xml中的配置的DispatcherServlet的"名称",如上面中的DispatcherServlet的名字为: SpringMvc,则servletName则替换为SpringMvc
    //所以最后会在web-inf目录下找到"SpringMvc-servlet.xml"的文件来充当"springmvc配置文件"
    servletName-servlet.xml

    其中,servletName ( 是根据实际情况而定不是固定的名字 )指的是部署在web.xml 中的 DispatcherServlet名称 ,在上面 web.xm中配置代码中 即为SpringMvc ,而 -servlet.xml 是配置文件名固定写法 ,所以应用程序 会在 WEB-INF 下寻找 "SpringMvc-servlet.xml " (来充当"springmvc配置文件")。

    注意点 :(重点,重点,重点

    ( 如果在 web.xml 中 配置"前端控制器 "时,没有通过<init-param>元素 进行添加"Springmvc配置文件springmvc-config.xml "的位置 的话,应用程序会到web-inf目录 下找名字为 :"servletName-servlet.xml " 的文件充当 "springmvc配置文件"。)

2.@Controller 注解

  • org.springframework.stereotype .Controller 注解类型 ( @Controller )用于指示 Spring 类实例 是一个控制器,其注解形式@Controller 。该 注解在使用不需要再实现Controller 接口 (通过将加 @Controller注解 的方式来替代"实现controller接口" ),只需要将 @Controller注解 加入到控制器类 上,然后通过Spring扫描机制 找到标注了该注解的控制器即可

    java 复制代码
    /**
     * 控制器类
      可用实现"@Controller"接口来 替代implements Controller (两者都能实现相同的效果)
     */
    /**
     * ① 此处使用@Controller注解的方式来替代 实现"controller接口",此时要通过设置    	   *@RequestMapping()注解来映射URL
     *  ②使用注解后,要配置<context:component-scan>元素来进行"指定要扫描的包",让注解生效
     */
    public class FirstController2 implements Controller {
    
        //其中的方法要配合@RequestMapping注解一起使用
    
    }

    为了保证 Spring 能够找到控制器类,还需要在SpringMVC的配置文件 ( springmvc-config.xml )中添加相应的 扫描配置信息 (用 <context:component-scan>元素 ,来指定需要扫描的包,来进行 "根包扫描 "),( springmvc-config.xml ) 具体配置信息 如下 :

    xml 复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           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">
    
        <!--  配置"根包扫描",指定需要扫描的包  -->
        <context:component-scan base-package="com.myh.controller"/>
    
    </beans>

    注意点1 : ① 与 实现controller接口 不同,使用 @Controller注解 的类中的方法通常使用 @RequestMapping注解映射URL ,这样你可以更直观地映射请 求到具体的方法 。此外,@controller注解 通常与 @Autowired等注解 一起使用,以实现依赖注入 ,这使得控制器之间的解耦

    更为方便。

    ② 在使用@controller注解的类中,你可以使用 @ModelAttribute@RequestParam等注解 来自动绑定请求参
    ,也可以使用 @ResponseBody注解 来直接将方法返回 值写入响应体 ,这使得处理请求和响应更为简洁

    注意点2

    使用注解方式 时,程序的运行 需要依赖Spring的 AOP 包,因此需要向 lib目录中添加spring-aop-.jar否则程序运行时会报错

    spring-aop.jar

3.RequestMapping 注解

3.1 @RequestMapping 注解的 "使用"

  • Spring 通过 @Controller 注解 找到相应的控制器类 后,还需要知道控制器内部每一个请求 是如何处理的,这就需要使用org.springframework.web.bind.annotation.RequestMapping注解类型。

  • RequestMapping注解类型 用于 映射一个请求一个方法 ,其注解形式为 : @RequestMapping,可以使用该注解 标注在 一个方法 或一个类上

    ( 即通过 @Controller注解 则用于 标记"控制器类 ",@RequestMapping注解 则用于 "映射一个方法或一个类" :即前端发送的 "url请求" 通过 "@RequestMapping注解" 能找到对应 的"方法 "上,"类或方法 "则对请求做出"响应"。)

    前端url请求 --找到"控制器 " ---再根据自身携带"url请求信息 ",对比"@RequestMapping 中的url信息 ",找到能做出"响应"方法。)

标注在 "方法" 上
  • 标注 在一个方法 上时,该方法 将成为一个请求处理方法,它会在程序接收到对应URL请求时被调用 (即前端的url请求信息 和 该方法上的@RequestMapping( )注解的 url信息一致该方法就会被调用)。

    java 复制代码
    /**
     * 控制器类
     */
    @Controller //比较该类为"控制器类"
    public class FirstController  {
    
        /**
         * 为"前端的url请求" 和 该"方法"中的"/firstController" 设立URL映射关系 :
         * 只要是 /firstController 的前端url请求 就会请求到该方法上, 执行该方法,并作出响应。
         */
        @RequestMapping(value = "/firstController") 
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
               ...
               return mav;
        }
    }

    使用 @RequestMapping注解 后,上述代码中的 handleRequest( )方法 就可以通过地址:

    http://localhost:8080/springMVC_Demo/firstController 进行访问

标注在 "类" 上
  • @RequestMapping注解 标注在一个类 上时,该类中的所有方法 都将映射为相对于类级别请求 ,表示该控制器 所处理的所有请求 都被映射到value属性 值所指定的路径下

    简而言之 :
    @RequestMapping 用在 上,就表明前端能通过"url路径 / url请求" 找到被 @RequestMapping标记 的"控制器类"上,将 "控制器类 " 和 "前端url请求" 进行URL映射绑定。)

    java 复制代码
    /**
     * 控制器类
     */
    @Controller //比较该类为"控制器类"
    @RequestMapping(value = "hello") //前端的"url请求"能找到该"控制器类"
    public class FirstController3  {
    
        @RequestMapping(value = "/FirstController3")
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
               ...
               return mav;
        }
    }

    由于在 "控制器类"上 添加了 @RequestMapping 注解,并且其value 属性值为"/hello",所以上述
    码中handleRequest( )方法请求路径将变为:http://localhost:8080/springMVC_Demo/hello/firstController。如果该**类中还包含其他方法** ,那么在其他方法的请求路径中 也需要加入"/hello"。

3.2 @RequestMapping 注解的 "属性"

  • @RequestMapping注解 中 "属性"-详解

    属性 类型 描述
    name String 可选属性 ,用于为映射地址 指定别名
    value (默认属性) String[] 可选属性 ,同时也是 默认属性,用于映射一个请求一种方法,可以标注在 一个方法一个类上ps : 当 value其唯一属性 时,可以省略属性名 ,即当注解中 只有value一个属性 时,可省略不写value ( 省略属性名 )
    method RequestMethod[] 可选属性 ,用于 指定 该方法用于处理哪种类型请求方式,其请求方式 包括 GETPOSTHEADOPTIONSPUTPATCHDELETETRACE 。 例如 method=RequestMethod.GET 表示只支持 GET 请求 ,如果需要支持多个请求方式 则需要通过 { }写成数组的形式 ,并且多个请求方式之间 是有英文逗号分隔
    params String[] 可选属性 ,用于指定Request 中 必须包含某些参数的值 ,才可以通过其标注的方法处理
    headers String[] 可选属性 ,用于指定Request必须包含 某些指定的header的值,才可以通过其标注的方法处理。
    consumes String[] 可选属性 ,用于指定处理请求提交内容类型( Content-type ),比如 application/jsontext/html 等。
    produces String[] 可选属性 ,用于指定返回内容类型返回的内容类型 必须是request请求头 ( Accept )中所包含的类型

    在上表中,所有属性 都是可选的,但其 默认属性value。当 value其唯一属性 时,可以省略属性名 ,例如下面两种标注的含义 相同 (因为只有value这个一个属性 ) :

    java 复制代码
    /**
     * 因为只有value这一个属性,所以value这个属性名可以省略不写。
     * (这两个注解含义相同)
     */
    @RequestMapping(value = "hello") 
    @RequestMapping("hello") 

4.组合注解

  • Spring框架的4.3版本中引入组合注解,来帮助简化常用的HTTP 方法映射 ,并更好地表达被注解方法语义 。其组合注解如下所示 :

    @GetMapping : 匹配 GET 方式请求
    @PostMapping : 匹配 POST 方式请求
    @PutMapping : 匹配 PUT 方式请求
    @DeleteMapping : 匹配 DELETE 方式请求
    @PatchMapping : 匹配 PATCH方式请求

  • @GetMapping 为例,该 组合注解@RequestMapping(method = RequestMethod.GET)

    缩写,它会将 HTTP GET映射 到特定的处理方法上。

    例子如下

    传统的@RequestMapping注解使用方式 如下 :

    java 复制代码
     //"传统"的@RequestMapping注解使用方式
        @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
        public String selectUserById(String id) {
            ....
      }

    新注解 : @GetMapping使用方式 如下 :

    java 复制代码
        //"新注解 :@GetMapping注解的使用
        //新注解比"传统的注解方式" 使用起来更简单
        @GetMapping(value = "/user{id}")
        public String selectUserById(String id) {
            ....
        }

    新注解 ( 组合注解 )比"传统的注解方式 " 使用起来更简单 ,可以省略method属性

4.1 请求处理方法的 "参数类型" 和 "返回值类型"

请求处理方法中的 "参数类型"
  • 控制器类 中,每一个请求处理方法 都可以有多个不同类型参数 ,以及一个多种类型返回结果。例如在入门案例 中,handleRequest()方法参数 就是对应请求的 HttpServletRequestHttpServletResponse 两种参数类型。除此之外,还可以使用其他的参数类型,例如在请求处理方法中需要访问HttpSession 对象,则可以添加 HttpSession 作为 参数,Spring会将对象正确地传递给方法,其使用示例如下 :

    java 复制代码
        @GetMapping(value = "/user{id}")
        public String selectUserById(HttpSession session) { //该"请求处理方法"的参数为 : HttpSession
            ....
        }
  • 请求处理方法 中, 可以出现参数类型 如下:(注意: 下面的"请求方法 "中的"参数内容" )

    .javax.servlet.ServletRequest / javax.servlet.http.HttpServletRequest

    javax.servlet.ServletResponse / javax.servlet.http.HttpServletResponse

    javax.servlet.http.HttpSession

    org.springframework.web.context.request.WebRequest

    org.springframework.web.context.request.NativeWebRequest

    java.util.Locale

    java.util.TimeZone (Java 6+) / java.time.Zoneld (on Java 8)

    java.io.InputStream / java.io.Reader

    java.io.OutputStream / java.io.Writer

    org.springframework.http.HttpMethod

    java.security.Principal
    @PathVariable@MatrixVariable@RequestParam@RequestHeader@RequestBody
    @RequestPart@SessionAttribute@RequestAttribute 注解
    HttpEntity<?>

    java.util.Map / org.springframework.ui.Model / org.springframework.ui.ModelMap

    .org.springframework.web.servlet.mvc.support.RedirectAttributes

    org.springframework.validation.Errors /org.springframework.validation.BindingResult

    org.springframework.web.bind.support.SessionStatus

    ·org.springframework.web.util.UriComponentsBuilder

    ps :
    需要注意的是 ,org.springframework.ui.Model类型不是一个Servlet API类型,而是一个包含了 Map 对象Spring MVC 类型。如果方法中添加Model 参数 ,则每次调用该请求处理方法时 ,Spring MVC 都会创建Model对象 ,并将其作为参数传递给方法

请求处理方法的 "返回值类型"
  • 在上面代码案例中,请求处理方法返回 的是一个ModelAndView类型数据 ( 请求处理方法返回值类型 为 :ModelAndView类型 )。除了此种类型外请求处理方法 还可以返回其他类型的数据

  • Spring MVC 所支持常见方法返回类型 ( 返回值类型 )如下 :

    返回值类型 描述
    ModelAndView (常用) ModelAndView 类型中可以 添加Model 数据,并 指定视图
    Model (常用) ---------
    Map ---------
    View
    String (常用 ) ps : 实际开发中通用String 类型跳转""视图"" + Model参数 传递"属性值"。 String类型返回值 可以跳转视图,但不能携带数据。 ps : String 类型除了可以跳转"视图 "外,还能 "重定向 " 和 "请求转发"。
    void (常用) void类型 主要在 异步请求时使用,它只返回数据 ,而不会跳转视图
    HttpEntity<?>ResponseEntity<?> ---------
    Callable<?> ---------
    DeferredResult<?> ---------

    注意点 :

    由于==ModelAndView 类型未能实现数据与视图之间解耦 ,所以在企业开发时,方法返回类型 通常都会使用String 。既然 String 类型返回值不能携带数据 ,那么在方法中 是如何将数据带入视图页面的呢 ?这就用到 ==了上面所讲解的 Model 参数类型 ( Mode类型 : 属于处理方法 中的 参数类型 ),通过该参数类型 ,即可添加需要在视图中显示属性

    实际开发 中,常用 的是 :
    通过String 类型跳转""视图" " 通过Model参数 类型传递"属性值"

    java 复制代码
    @Controller //比较该类为"控制器类"
    @RequestMapping(value = "/firstController") //前端的"url请求"能找到该"控制器类"
    public class FirstController3  {
    
        @GetMapping(value = "/firstController")
        //返回值类型为 : String : 可跳转"视图"。
        //处理方法中的"参数类型" : Model(模型对象) : 可传递"属性"(给"视图")--通过Model向视图中添加传递数据
        public String selectUserById(HttpServletRequest request,
                                     HttpServletResponse response ,Model model)  {
            //向Model(模型对象)中添加数据 --进行数据的传递
            model.addAttribute("msg", "这是我的第一个Spring MVC程序。");
            //通过String类型返回"视图"
            return "WEB-INF/jsp/first.jsp";
        }
    }

    在上述方法代码 中,"处理方法 "中参数 的类型有 : Model (模型对象),通过该参数实例addAttribute( )方法即可添加所需数据 。"处理方法 "的返回值类型 为 : String类型String类型 除了可以返回上述代码中视图页面 外,还可以进行 重定向请求转发

通过返回值"String类型"进行 "重定向"
java 复制代码
 //通过String类型进行"重定向"
 @RequestMapping(value = "/update")
 //返回值类型为 : String ,此处通过String来进行"重定向"
 public String selectUserById(HttpServletRequest request,
                              HttpServletResponse response ,Model model)  {
     .....
     return "redirect:queryUser";
 }
通过返回值"String类型"进行 "请求forward转发"
java 复制代码
//通过String类型进行"forward请求转发"
 @RequestMapping(value = "/toEdit")
 public String selectUserById(HttpServletRequest request,
                              HttpServletResponse response ,Model model)  {
     .....
     return "forward:editUser";
 }

5.ViewResolver(视图解析器)

  • Spring MVC 中的 视图解析器 负责解析视图,可以通过在配置文件中 定义一个ViewResolver配置视图解析器其配置示例如下 :

    xml 复制代码
        <!--   配置"视图解析器" : 在"处理方法"中可直接写要返回的"视图文件名",不用写"该视图"对应的前后缀 -->
        <!--  在视图解析器中配置要返回的视图的对应的"前后缀"  -->
    	<!--  配置视图解析器 : 可简化在"处理方法"中要填的"视图的路径"  -->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
           <!--    设置返回的"视图"对应的"前缀"    -->
            <property name="prefix" value="/WEB-INF/jsp"/>
            <!--    设置返回的"视图"对应的"后缀"    -->
            <property name="suffix" value=".jsp"/>
        </bean>

    上述代码 中,定义了一个idviewResolver视图解析器,并设置了 视图的前缀后缀 属性。这样设置后,方法中所定义view 路径可以简化。例如,上面例子 中的逻辑视图名 只需设置为"first ",而不再需要设置为"WEB-INF/jsp/first.jsp" (配置了前后置,现在只return "first" 就能返回一个视图 ),在访问时视图解析器自动地增加前缀后缀

相关推荐
Kay_Liang14 分钟前
大语言模型如何精准调用函数—— Function Calling 系统笔记
java·大数据·spring boot·笔记·ai·langchain·tools
自由的疯30 分钟前
Java 如何学习Docker
java·后端·架构
自由的疯32 分钟前
Java Docker本地部署
java·后端·架构
007php00733 分钟前
猿辅导Java面试真实经历与深度总结(二)
java·开发语言·python·计算机网络·面试·职场和发展·golang
摇滚侠36 分钟前
Spring Boot 3零基础教程,WEB 开发 内容协商机制 笔记34
java·spring boot·笔记·缓存
一勺菠萝丶37 分钟前
在 macOS 上用 Docker 为 Java 后端 & 常见开发需求搭建完整服务(详尽教程)
java·macos·docker
顾漂亮43 分钟前
JVM底层攻坚
java·jvm·spring
编程岁月44 分钟前
java面试-0215-HashMap有序吗?Comparable和Comparator区别?集合如何排序?
java·数据结构·面试
William_cl1 小时前
ASP.NET MVC 前置基础:宿主环境 & HttpRuntime 管道,从部署到流程拆透(附避坑指南)
后端·asp.net·mvc
木井巳1 小时前
[Java数据结构与算法]详解排序算法
java·数据结构·算法·排序算法