前言

小伙伴们,大家好,我是狂奔の蜗牛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/beanshttp://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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttp://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") //再访问/hello2public 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版通俗易懂

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

  1. SpringMVC基础学习之Restful风格的简单使用

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

  2. React基础学习笔记(一)-react前端项目的两种搭建方式

    1.运行环境准备 需要先进行react项目的运行环境nodeJS的安装,具体安装流程可以参考: windows版本的安装配置帮助文档:https://www.cnblogs.com/liuqiyun/ ...

  3. controller 有两种写法,讨论一下两种写法的区别:

    controller 有两种写法,讨论一下两种写法的区别: 写法 1: app.controller('myCtrl', function($scope, $location) { $scope.my ...

  4. android中资源文件的两种访问方式,Android_Android学习笔记-保存文件(Saving Files),Android设备有两种文件存储区域 - phpStudy...

    Android学习笔记-保存文件(Saving Files) Android设备有两种文件存储区域: 内部存储和外部存储 ("internal" and "externa ...

  5. JavaSE学习总结(八)常用类(上)Object类==与equals方法的区别浅克隆的特点Scanner类String类String两种创建对象方式的区别String类的各种功能

    JavaSE学习总结(八)常用类(上)/Object类/==与equals方法的区别/浅克隆的特点/Scanner类/String类/String两种创建对象方式的区别/String类的各种功能 常用 ...

  6. 【Django】项目中调用深度学习模型model.predict()(Django两种启动方式runserver和uwsgi的区别)

    目录 问题 测试 解决方法 Django两种启动方式runserver和uwsgi的区别 问题 部署含有深度学习模型的Django项目的uWSGI.Nginx服务器的时候,所有模块都可以正常运行,也可 ...

  7. php文本框限制字节,js限制文本框输入长度两种限制方式(长度、字节数)_基础知识...

    功能/特点: 1.实时显示可输入的字数(字节数) 2.两种限制方式(长度.字节数) 3.中文输入法下可正常使用,无BUG 4.同一页面可以使用多个,相互不干扰 limit.js function li ...

  8. python定义字符串变量有两种常用方式_Python 1基础语法二(标识符、关键字、变量和字符串)...

    一.标识符 标识符就是程序员自己命名的变量名.名字需要有见名知义的效果,不要随意起名 :比如 a=1 a是个变量,a这个变量名属于标识符 1 company = '小米 2 employeeNum = ...

  9. 方向gravity_两种对齐方式,layout_gravity和gravity大不同

    原标题:两种对齐方式,layout_gravity和gravity大不同 上一期我们一起学习了LinearLayout线性布局的方向.填充模型和权重,本期来一起学习LinearLayout线性布局的对 ...

最新文章

  1. OpenGL材质和光照(转)part2
  2. [bzoj2893] 集合计数
  3. c++ uint32转为int_【转】用python将GBK编码文件转为UTF-8编码文件
  4. 【redis】在windos下的redis服务器的搭建
  5. android 隐藏所有 fragment,Android 隐藏Fragment
  6. 有关Silverlight TreeView组件的研究[2]——Silverlight学习笔记(7)
  7. 初始化 数组 java_如何用Java初始化数组
  8. mysql 5.5加服务器_mysql 5.5 安装配置方法图文教程
  9. 扩展方法:给 IEnumerableTSource 扩展一个自定义数据源绑定的方法
  10. 那些年使用Android studio遇到的问题
  11. java调用WebService接口工具
  12. 服务器的主板芯片组,关于P8系列服务器主板芯片组的一些事儿
  13. volatility内存取证分析与讲解(持续更新)
  14. codeforces水题100道 第九题 Codeforces Beta Round #63 (Div. 2) Young Physicist (math)
  15. Linux运维工程师笔试题系列6(30题)
  16. Caché的studio如何Debug
  17. 知乎版ChatGPT「知海图AI」加入国产大模型乱斗,称效果与GPT-4持平
  18. oracle及shell相关学习记录
  19. VPP使用介绍(route、tun、memif、abf)
  20. Jenkins mavn多模块单独编译一个模块

热门文章

  1. spring boot and php
  2. Salesforce Apex 中常用技能总结(持续更新)
  3. jdk9模块化简单介绍
  4. FastReport 分组按每组单独一页打印
  5. python path包的使用详解
  6. 排名趋于稳定后,最新的博主排名(TOP10)
  7. 关于拦截器与过滤器使用场景、拦截器与过滤器的区别整理
  8. 物联网毕设分享 stm32人体健康状态检测系统(项目开源)
  9. 面试题:Commonjs 和 Es Module区别
  10. 也谈“为什么中国的程序员总被称为码农?”