SpringMVC基础学习之Controller的两种实现方式和RequstMapping注解的使用

前言

小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java半年多时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。

这个SpringMVC基础学习系列是用来记录我学习SpringMVC框架基础知识的全过程 (这个系列是参照B站狂神的SpringMVC最新教程来写的,由于是之前整理的,但当时没有发布出来,所以有些地方可能有错误,希望大家能够及时指正!)


之后我将尽量以两天一更的速度更新这个系列,还没有学习SpringMVC框架的小伙伴可以参照我的博客学习一下;当然学习过的小伙伴,也可以顺便跟我一起复习一下基础。最后,希望能够和大家一同进步吧,加油吧,编程人!

特别提醒:如果对SpringMVC基础学习系列感兴趣,可以阅读本系列往期博客:
第一篇SpringMVC基础学习之简单回顾MVC架构和Servlet的使用
第二篇SpringMVC基础学习之初识SpringMVC
第三篇SpringMVC基础学习之初识
第四篇SpringMVC基础学习之使用注解开发


今天我们来到了SpringMVC基础学习的第五站:Controller的两种实现方式和RequstMapping注解的使用 。废话不多说,让我们开始今天的学习内容吧。

5.Controller的两种实现方式和RequstMapping注解的使用

5.1 什么是Controller?

  • Controller (即控制器) ,它主要负责提供访问应用程序的行为和解析用户的请求,并将其转换为一个模型,通常通过接口定义注解定义这两种方式来实现
  • Spring MVC中一个控制器类可以包含多个方法,并且对于 Controller的配置方式 包含多种,包括接口定义注解定义

5.2 实现Controller接口

5.1.1 了解Controller接口

  • Controller是一个接口,在org.springframework.web.servlet.mvc包下,为了进一步了解它,我们可以查看其源代码:
// 实现该接口的类获得控制器功能
public interface Controller {
    
    // 处理请求并返回一个模型与视图对象
    ModelAndView handleRequest(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
    
}

查看Controller接口的源码后,发现该接口中只有一个方法,即handleRequest方法,用来处理请求并返回一个ModelAndView(模型和视图)对象

5.1.2 创建HelloController类

  • src源文件下的java目录中创建一个com.kuang.controller包,创建HelloController类并且实现Controller接口
package com.kuang.controller;

import org.springframework.web.servlet.ModelAndView;
// 注意: 该Controller接口是servlet.mvc包下
import org.springframework.web.servlet.mvc.Controller; 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// 只要实现了Controller接口的类,说明这就是一个控制器了
public class HelloController implements Controller {
    
    /** 
     * 用于处理请求并返回一个模型与视图对象
     * @param: httpServletRequest http请求
     * @param: httpServletResponse http响应
     * @return ModelAndView 视图模型对象
     */
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        // 获取ModelAndView(模型视图)对象
        ModelAndView mv = new ModelAndView();
        // 封装数据到ModelAndView对象中
        mv.addObject("msg","Hello,Controller!");
        // 设置跳转视图, 存入到ModelAndView对象中
        mv.setViewName("hello");
        // 返回视图模型对象给视图解析器
        return mv;
    }
    
}

5.1.3 编写核心配置文件

1.编写web.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">
    
    <!-- 配置DispatcherServlet(前端控制器), SpringMVC中的核心,相当于请求分发器 -->
    <!-- 配置servlet -->
    <servlet>
        <!-- servlet的名字,自行设置 -->
        <servlet-name>springmvc</servlet-name>
        <!-- DispatcherServlet类的位置 -->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!-- 设置配置文件的位置 -->
            <param-name>contextConfigLocation</param-name>
            <!-- 配置文件的路径 -->
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        <!-- 设置启动优先级为1 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <!-- 配置servlet映射 -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!-- 注意:在SpringMVC中, / 和 /* 作用不同
             / : 匹配所有的请求,不会匹配jsp页面
             /*: 匹配所有的请求,包括jsp页面 -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
</web-app>

2.编写springmvc-servlet.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"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 显式引入处理器映射和处理器适配器,也可以不写,因为Spring已经帮我们引入了 -->       
    <!-- 配置处理器映射器 -->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    
    <!-- 配置处理器适配器 -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    <!-- 配置internalResourceViewResolver(视图解析器), 主要作用是解析DispatcherServlet(中心控制器)给它的ModelAndView -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"/>
        <!-- 注意: 在视图解析器中我们吧所有的视图都放在/WEB-INF/目录下, 这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问) -->
    </bean>
    
    <!-- 注册控制器HelloController的Bean信息,交由Spring的IOC容器进行管理;
         该bean标签中的包含两个属性class和name, 其中"class"对应处理请求的控制类, 而"name"对应请求路径-->
    <bean class="com.kuang.controller.HelloController" name="/hello"/>
    
</beans>

5.1.4 实现Controller接口使用总结

优点

  • 逻辑简单,易于理解
  • 比起使用传统的Servlet,配置文件的编写简便了许多

缺点

  • 与使用注解相比,配置文件和控制层代码还是略过繁琐
  • 每个控制层只能控制一个跳转页面,页面无法复用

5.3 使用@Controller注解

5.1.1 了解常用注解

@Component:注册为组件
@Repository:注册为Dao持久层
@Service:注册为Service服务层
@Controller:注册为Controller控制层

5.1.2 创建HelloController控制器类

  • src源文件下的java目录下创建一个com.kuang.controller包,创建HelloController2类
package com.kuang.controller;

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

// 使用@Controller注解, 将其注册为控制层, 由Spring的IOC容器统一管理
@Controller
public class HelloController2 {
    
    /**
     * 使用@Controller注解注解的类中的所有方法, 
     * 如果返回类型是String, 并且有具体的页面可以跳转, 那么就会被视图解析器解析 
     */

    // 使用@RequestMapping注解, 设置请求映射, 其作用域是类或者方法
    @RequestMapping("/h1")
    public String hello(Model model) {
        // 封装数据:向模型中添加属性msg与其值,可以在JSP页面取出并且渲染
        model.addAttribute("msg","Hello,Controller!");
        // 会被视图解析器处理,注意:这里的hello对应的是JSP页面的名字
        return "hello";
    }
    
    // 使用@RequestMapping注解, 设置请求映射, 其作用域是类或者方法
    @RequestMapping("/h2") 
    public String hello2(Model model) {
        // 封装数据: 向模型中添加属性msg与其值,可以在JSP页面取出并且渲染
        model.addAttribute("msg","Hello,World!");
        // 会被视图解析器处理(注意: 这里的hello对应的是JSP页面的名字)
        return "hello";
    }
    
}

5.1.3 编写核心配置文件

1.编写web.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">
    
    <!-- 配置DispatcherServlet(前端控制器), SpringMVC中的核心,相当于请求分发器 -->
    <!-- 配置servlet -->
    <servlet>
        <!-- servlet的名字,自行设置 -->
        <servlet-name>springmvc</servlet-name>
        <!-- DispatcherServlet类的位置 -->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!-- 设置配置文件的位置 -->
            <param-name>contextConfigLocation</param-name>
            <!-- 配置文件的路径 -->
            <param-value>classpath:springmvc-servlet2.xml</param-value>
        </init-param>
        <!-- 设置启动优先级为1 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <!-- 配置servlet映射 -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!-- 注意:在SpringMVC中, / 和 /* 作用不同
             / : 匹配所有的请求,不会匹配jsp页面
             /*: 匹配所有的请求,包括jsp页面 -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
</web-app>

2.编写springmvc-servlet2.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">
    
    <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.kuang.controller"/>
    
     <!-- 设置default-servlet-handler用来防止静态资源被过滤 -->
    <mvc:default-servlet-handler/>
     <!-- 设置mvc的注解驱动, 让@RequstMapping注解生效以及引入DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter实例;
          使用annotation-driven会帮助我们自动完成上述两个实例的注入 -->
    <mvc:annotation-driven/>
    
    <!-- 配置internalResourceViewResolve(视图解析器): 主要作用是解析DispatcherServlet(中心控制器)给它的ModelAndView -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"/>
	</bean>
        
</beans>

5.1.4 测试结果

1.访问h1页面

在这里插入图片描述

2.访问h2页面

在这里插入图片描述

结果可以发现,我们的两个请求都指向一个视图,但是页面结果却是不一样的,从这里可以看出视图是被复用的,因此控制器视图之间是弱耦合关系

5.1.5 使用@Controller注解使用总结

优点

  • 使用注解开发,代码量大大减少,开发起来很方便
  • 配置文件的编写比实现Controller接口的更加简便
  • 一个控制器中可以写多个请求映射,从而实现跳转不同的视图
  • 也可以跳转同一视图,但显示结果不同,视图可以被复用

缺点

  • 配置信息少,使用大量注解,导致查看代码结构时不太方便
  • 代码可读性降低,不方便后期的代码维护

5.4 使用@RequstMapping注解

5.4.1 只在方法上使用

1.编写HelloController3对象

1-1 使用正常路径
  • hello.jsp页面的存放路径为WEB-INF/jsp/hello.jsp
package com.kuang.controller;

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

// 使用@Controller注解, 将该类注册为Controller接口, 交由Spring的IOC容器统一管理
@Controller
public class HelloController3 {
    
    /** 
     * 在hello()方法上使用@RequestMapping, 设置请求映射路径
     * 而真实访问路径为:http://localhost:8080/项目名称/hello
     */
    @RequestMapping("/hello")
    public String hello(Model model) {
        // 封装数据: 向模型中添加属性msg与其值,进行视图渲染
        model.addAttribute("msg","Hello,RequestMapping!");
        // 返回视图逻辑名,让视图解析器进行解析(注意:这里的hello是要跳转的视图逻辑名)
        return "hello"; 
    }
    
}
1-2 修改路径后
  • hello.jsp的存放路径修改为WEB-INF/jsp/user/hello.jsp,即在jsp文件下创建一个user,将hello.jsp放入其中
package com.kuang.controller;

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

// 使用@Controller注解, 将该类注册为Controller接口, 交由Spring的IOC容器统一管理
@Controller
public class HelloController3 {
    
    /** 
     * 使用@RequestMapping, 设置请求映射路径 (注意: 直接在方法上把路径补全)
     * 真实访问路径为:http://localhost:8080/项目名称/user/hello
     */
    @RequestMapping("/user/hello3") 
    public String hello3(Model model) {
        // 封装数据: 向模型中添加属性msg与其值,进行视图渲染
        model.addAttribute("msg","Hello,User!");
        // 返回视图逻辑名,让视图解析器进行解析 (注意: 由于路径发生了改变,因此要跳转的视图逻辑名也要相应变化)
        return "hello/user"; 
    }
    
}

建议这样使用@RequestMapping注解,即在方法前的映射请求中设置全路径

2.测试结果

2-1 使用正常路径

在这里插入图片描述

结果成功查询到了hello2页面,并且显示“Hello,RequestMapping!”信息

2-2 修改路径后

在这里插入图片描述

结果成功查询到了user/hello3页面,并且显示“Hello,User”信息!

5.4.2 在类和方法上同时使用

1.修改HelloController3控制类

  • hello.jsp的存放路径仍然为WEB-INF/jsp/user/hello.jsp
package com.kuang.controller;

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

// 使用@Controller注解, 将该类注册为Controller接口, 交由Spring的IOC容器统一管理
@Controller
// 在控制类上使用@RequestMapping: 相当于在URL链接上再加一个父目录进行区分 
@RequestMapping("/user") // 先访问类上的/user
public class HelloController3 {
    
    // 真实访问路径变为了:http://localhost:8080/项目名称/user/hello2
    @RequestMapping("/hello2") //再访问/hello2
    public String hello2(Model model) {
        // 封装数据:向模型中添加属性msg与值,进行视图渲染
        model.addAttribute("msg","Hello,RequestMapping2!");
        // 返回视图逻辑名,让视图解析器进行解析 (注意: 由于路径发生了改变,因此要跳转的视图逻辑名也要相应变化)
        return "user/hello"; 
    }
    
}

2.测试结果

在这里插入图片描述

结果成功查询到了user/hello2页面,并且显示“Hello,RequestMapping2!”信息

5.4.3 使用总结

  • 只在方法上使用@RequestMapping注解,代码编写更加简便,只用在每个方法前设置映射关系,而且方法中的页面的路径选择更加宽泛
  • 在类和方法上同时使用@RequestMapping注解,逻辑更加清晰,但页面的调用范围也受到了限制,即只能调用在类上的映射关系中设置的父目录下的页面

好了,今天的有关 Controller的两种实现方式和RequstMapping注解的使用 的学习就到此结束啦。欢迎小伙伴们积极学习和讨论,喜欢的可以给蜗牛君点个关注,顺便来个一键三连。我们下期见,拜拜啦!


参考视频链接【狂神说Java】SpringMVC最新教程IDEA版通俗易懂

  • 1
    点赞
  • 2
    收藏
  • 打赏
    打赏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:技术工厂 设计师:CSDN官方博客 返回首页
评论

打赏作者

狂奔の蜗牛rz

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值