Springmvc 讲解(1)

文章目录


前言

再此之前,我已经学习也发过了关系maven,SpringFramework以及Mybatis的文章了,

现在,我们开始来学习关于SpringMvc这个控制层框架。

一、SpringMvc

1、简介

Spring Web MVC是基于Servlet API构建的原始Web框架,从一开始就包含在Spring Framework中。正式名称"Spring Web MVC"来自其源模块的名称( spring-webmvc ),但它通常被称为"Spring MVC"。

在没有SpringMvc该框架之前,我们都是使用servlet以及过滤器等来接收前端信息或者返回给用户信息,Springmvc可以帮助我们1. 简化前端参数接收( 形参列表 )2. 简化后端数据响应(返回值),这也是Springmvc最主要的两个功能。

2、核心组件和调用流程

Spring MVC与许多其他Web框架一样,是围绕前端控制器模式设计的,其中中央 Servlet DispatcherServlet 做整体请求处理调度!

除了DispatcherServletSpringMVC还会提供其他特殊的组件协作完成请求处理和响应呈现。

2.1 涉及组件的理解

  1. DispatcherServlet : SpringMVC提供,我们需要使用web.xml配置使其生效,它是整个流程处理的核心,所有请求都经过它的处理和分发![ CEO ]
  2. HandlerMapping : SpringMVC提供,我们需要进行IoC配置使其加入IoC容器方可生效,它内部缓存handler(controller方法)和handler访问路径数据,被DispatcherServlet调用,用于查找路径对应的handler![秘书]
  3. HandlerAdapter : SpringMVC提供,我们需要进行IoC配置使其加入IoC容器方可生效,它可以处理请求参数和处理响应数据数据,每次DispatcherServlet都是通过handlerAdapter间接调用handler,他是handler和DispatcherServlet之间的适配器![经理]
  4. Handler : handler又称处理器,他是Controller类内部的方法简称,是由我们自己定义,用来接收参数,向后调用业务,最终返回响应结果![打工人]
  5. ViewResovler : SpringMVC提供,我们需要进行IoC配置使其加入IoC容器方可生效!视图解析器主要作用简化模版视图页面查找的,但是需要注意,前后端分离项目,后端只返回JSON数据,不返回页面,那就不需要视图解析器!所以,视图解析器,相对其他的组件不是必须的![财务]

自己的理解:

在我们前端访问页面时,需要访问一个地址,该访问页面会调用我们java中的一个方法(Handler),HandlerMapping 相当于将我们的访问地址与该Handler 映射,访问所有地址都会先经过Dispatcherservlet(CEO),去查HandlerMapping(秘书)有没有该地址对应的方法,如果有,接着HandlerAdapter(经理)服务,它是handler与dispatchersevlet的一个适配器,用来将我们的request内容变为我们handler可以直接接收的字符,同时也可以将handler返回的json等变回浏览器支持的格式,ViewResovler(财务)可以简化模板视图页面的查找,可以添加一个统一的前缀与后缀,比如前缀为 cky/ 后缀为.html 如果我们直接返回 login 就会自动拼接成cky/login.html 会自动去返回该模板页面。ViewResovler并不是必须的,如果后端不返回页面,就不需要视图解析器。

3、小案例快速体验

3.1场景需求

![在这里插入图片描述](https://img-blog.csdnimg.cn/11b2a36dcd1e476a9e2d5851e46bfb32.png![在这里插入图片描述](https://file.jishuzhan.net/article/1719155463074877441/3e4762c95bb6b3a7de41a4b44122d7fa.webp)

创建一个idea maven项目(注意导成web项目),编写handler方法,请求响应一个输出。

3.1.1 导入依赖
python 复制代码
<properties>
    <spring.version>6.0.6</spring.version>
    <servlet.api>9.1.0</servlet.api>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
    <!-- springioc相关依赖  -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <!-- web相关依赖  -->
    <!-- 在 pom.xml 中引入 Jakarta EE Web API 的依赖 -->
    <!--
        在 Spring Web MVC 6 中,Servlet API 迁移到了 Jakarta EE API,因此在配置 DispatcherServlet 时需要使用
         Jakarta EE 提供的相应类库和命名空间。错误信息 "'org.springframework.web.servlet.DispatcherServlet'
         is not assignable to 'javax.servlet.Servlet,jakarta.servlet.Servlet'" 表明你使用了旧版本的
         Servlet API,没有更新到 Jakarta EE 规范。
    -->
    <dependency>
        <groupId>jakarta.platform</groupId>
        <artifactId>jakarta.jakartaee-web-api</artifactId>
        <version>${servlet.api}</version>
        <scope>provided</scope>
    </dependency>

    <!-- springwebmvc相关依赖  -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>

</dependencies>
3.1.2 controller声明
python 复制代码
@Controller
public class HelloController {

    //handlers

    /**
     * handler就是controller内部的具体方法
     * @RequestMapping("/springmvc/hello") 就是用来向handlerMapping中注册的方法注解!
     * @ResponseBody 代表向浏览器直接返回数据!
     */
    @RequestMapping("/springmvc/hello")
    @ResponseBody
    public String hello(){
        System.out.println("HelloController.hello");
        return "hello springmvc!!";
    }
}
3.1.3 核心配置类

声明springmvc涉及组件信息的配置类`

java 复制代码
//TODO: SpringMVC对应组件的配置类 [声明SpringMVC需要的组件信息]

//TODO: 导入handlerMapping和handlerAdapter的三种方式
 //1.自动导入handlerMapping和handlerAdapter [推荐]
 //2.可以不添加,springmvc会检查是否配置handlerMapping和handlerAdapter,没有配置默认加载
 //3.使用@Bean方式配置handlerMapper和handlerAdapter
@EnableWebMvc     
@Configuration
@ComponentScan(basePackages = "com.atguigu.controller") //TODO: 进行controller扫
//WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现
public class SpringMvcConfig implements WebMvcConfigurer {

    @Bean
    public HandlerMapping handlerMapping(){
        return new RequestMappingHandlerMapping();
    }

    @Bean
    public HandlerAdapter handlerAdapter(){
        return new RequestMappingHandlerAdapter();
    }
    
}
3.1.4 环境搭建

对于使用基于 Java 的 Spring 配置的应用程序,建议这样做,如以下示例所示:

python 复制代码
//TODO: SpringMVC提供的接口,是替代web.xml的方案,更方便实现完全注解方式ssm处理!
//TODO: Springmvc框架会自动检查当前类的实现类,会自动加载 getRootConfigClasses / getServletConfigClasses 提供的配置类
//TODO: getServletMappings 返回的地址 设置DispatherServlet对应处理的地址
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

  /**
   * 指定service / mapper层的配置类
   */
  @Override
  protected Class<?>[] getRootConfigClasses() {
    return null;
  }

  /**
   * 指定springmvc的配置类
   * @return
   */
  @Override
  protected Class<?>[] getServletConfigClasses() {
    return new Class<?>[] { SpringMvcConfig.class };
  }

  /**
   * 设置dispatcherServlet的处理路径!
   * 一般情况下为 / 代表处理所有请求!
   */
  @Override
  protected String[] getServletMappings() {
    return new String[] { "/" };
  }
}
3.1.6 配置tomcat


"注意选择 Tomcat Server
之后又出现了Tomcat 8080 in use的问题

解决办法点击此处

3.1.7 测试

二、SpringMvc 接收参数

1.路径设置注解

java 复制代码
package com.cky.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller  //组件
@ResponseBody  //直接返回给浏览器信息
@RestController //==Controller+ResponseBody
@RequestMapping("/user")
public class UserContorller {
    @RequestMapping //什么都不加 表示直接使用类方法上的访问地址
    public String index(){
        return null;
    }
    @GetMapping("/login")
    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public String login(){
        return null;
    }
    @RequestMapping("/register")
    public String register(){
        return null;
    }
}

注解:

复制代码
/**
 * RequestMapping 地址映射
 * RequestMapping 对/的要求不高 比如/user/login 也可以写成 user/login 或者/user/login/
 * WebSevrlet  开头就必须加/
 * 1、精准地址:可以1个也可以多个 多个的时候 用{地址1,地址2...}
 * 2、模糊地址 
 *     * 表示一层模糊  **表示任意层模糊
 *     比如 user/* ===》user/a user/b 等
 *     user/** ===》 user/a/b/...   user  等
 * 3、类上和方法上添加@ReqquestMapping 的区别:
 *    类上 可以不加 加的话 表示一个通用的地址
 *    方法上必须加  表示精准的访问地址
 *    如果类上没有 则直接使用方法上的
 *    如果类上有 访问地址就是类上+方法上的
 * 4、请求方式指定
 * get、post、put、delete
 * 客户端->http->ds->handler
 * 默认不加请求方式情况 是任何访问都可以
 * 请求方式指定 比如:    @RequestMapping(value = "/user/login",method = RequestMethod.POST)
 *          可以多个    @RequestMapping(value = "/user/login",method = {RequestMethod.POST,RequestMethod.GET})
 * 如果请求方式不正确,会返回405异常
 * 5、注解进阶 这种只能用在方法上!!!
 *   get  @GetMapping("/login")==》 @RequestMapping(value = "/login",method = RequestMethod.GET)
 *   post @PostMapping("/login")
 *   put @PutMapping("/login")
 *   delete @DeleteMapping("/login")
 */

2、param接收参数四种类型

2.1 直接接收值

直接接值 可传可不传 不传不会报错 传值必须与形参名相同
对于这种不用返回视图函数的 记得加上 @ResponseBody //表示我们直接向浏览器返回数据
否则浏览器会报错

复制代码
     @RequestMapping("emp/login")
    public String login(String name,Integer age){
     System.out.println("name:"+name+",age:"+age);
     return "name:"+name+",age:"+age ;
    }

2.2 @RequetParam

复制代码
//@RequestParam(name/value="重置参数名",required="true/false" 【默认为true,当配置为false时,我们可以配置默认值】,defaultValue)
// 注解  默认是必须传值 当设置为false时 可以设置默认值
@RequestMapping("emp/register")

public String register(@RequestParam(value = "user",required = false,defaultValue = "root") String username, int pwd){
    System.out.println("name:"+username+",pwd:"+pwd);
    return "name:"+username+",pwd:"+pwd ;
}

2.3 一名多值

参数上必须要加上@RequestParam,不然就会只将一个值 直接传给列表接收

复制代码
 //一key 多值
    @RequestMapping("emp/test")
    public String test(@RequestParam List<String> hbs){
         System.out.println(hbs);
         return "ok";
    }

2.4 实体类型

首先要有实体类 有get和set方法

复制代码
package com.cky.pojo;

import lombok.Data;

@Data
public class Employee {
  private String name;
  private int age;
}

//实体类接收
  @RequestMapping("emp")
  public  String employee(Employee employee){
       System.out.println(employee);
       return employee.getName();
  }

}性来传值,实体类属性可以直接再实体类上设置默认值。

3、路径参数接收

比如 user/root/123456

root 和123456 是我们要接收的参数

在这里 我们就要设置动态路径参数 {key}代表这里是路径参数
参数上 要加@PathVariable 注解
证明接收的是路径参数 否则会按照@Param参数来接值
该注解 也可以重置参数名 以及可以确定是否必须传参数 以及默认值

复制代码
   传入时必须按照实体类属   //路径参数接收
 @RequestMapping("path/{name}/{pwd}")
 public String path(@PathVariable String name,@PathVariable Integer pwd){
      System.out.println("name:"+name+",pwd:"+pwd);
      return "name:"+name+",pwd:"+pwd;

4、json格式接收参数

前端传递 JSON 数据时,Spring MVC 框架可以使用 @RequestBody 注解来将 JSON 数据转换为 Java 对象。@RequestBody 注解表示当前方法参数的值应该从请求体中获取,并且需要指定 value 属性来指示请求体应该映射到哪个参数上。

其使用方式和示例代码如下:

1、前端发送 JSON 数据的示例:(使用postman测试)

复制代码
{
"name": "张三",
"age": 18,
"gender": "男"
}

2、定义一个用于接收 JSON 数据的 Java 类,例如:

复制代码
@Data
public class Person {
private String name;
private int age;
private String gender;
// getter 和 setter 略
}

3、创建一个handler

在控制器中,使用 @RequestBody 注解来接收 JSON 数据,并将其转换为 Java 对象,例如:

复制代码
  package com.cky.controller;
  import com.cky.pojo.Person;
  import org.springframework.stereotype.Controller;
  import org.springframework.web.bind.annotation.PostMapping;
  import org.springframework.web.bind.annotation.RequestBody;
  import org.springframework.web.bind.annotation.ResponseBody;
  @Controller
  @ResponseBody
  public class PersonController {
@PostMapping("/json/data")
//RequestBody 代表我们接收的是信息体
//java并不接收 json的数据格式 我们需要配置
public String test(@RequestBody Person person){
    System.out.println(person);
    return person.getName()+person.getGender();
}}    

4、配置json转换器

java原生并不接收json数据,我们需要进行配置,

让Handleradapter 可以进行json转换

首先导入json依赖

java 复制代码
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.0</version>
</dependency>

接着要在配置类上加上**@EnableWebMvc**注解。效果等同于在 XML 配置中,可以使用 <mvc:annotation-driven> 元素!我们来解析<mvc:annotation-driven>对应的解析工作!

@EnableWebMvc注解表示 让HandlerAdapter配置了json转化器

5、结果

5、@EnableWebMvc 注解

在配置类上添加上 该注解,效果等同于在 XML 配置中,可以使用 <mvc:annotation-driven> 元素!

使用该注解 就等同于同时添加上了 我们所谓的经理Handleradapter和秘书Handlermapping,同时为经理添加上了json转换器,写上该注解之后,其实配置类中就不用导入第三方经理和秘书的类。

可省略:

java 复制代码
 @Bean
    public HandlerAdapter HandlerMapping(){
        return new RequestMappingHandlerAdapter();
    }
    @Bean
    public HandlerMapping handlerMapping(){
        return new RequestMappingHandlerMapping();
    }

6、接收请求头和cookie

6.1 接收请求头

接收请求头 要加上注解 @RequestHeader(xxx) xxx代表我们要接收请求头的内容

python 复制代码
@Controller
@ResponseBody
public class HeaderContorller {
    @RequestMapping("header")
    public String cookie(@RequestHeader("Host") String host){
        return host;
    }
}

6.2 接收Cookie

可以使用 @CookieValue 注释将 HTTP Cookie 的值绑定到控制器中的方法参数。

python 复制代码
  @RequestMapping("save")
    public String save(HttpServletResponse httpServletResponse){
        Cookie cookie=new Cookie("username","root");
        httpServletResponse.addCookie(cookie);//保存了一个cookie 名为username 值为root
        return "ok";
    }
    @RequestMapping("cookie")
    //通过@CookieValue 来获取相应cookie值的内容
    public String cookie(@CookieValue("username") String name){
        return name;

    }

7、原生API的获取

比如java的一些原生api,我们可以在形参列表中自动获取

比如:

python 复制代码
  @Autowired //直接注入 ioc容器获取该类的组件对象 装配到ioc容器中
    private ServletContext servletContext;
    public String apiget(HttpServletResponse httpServletResponse, HttpServletRequest httpServletRequest, HttpSession httpSession){
        //接下来要进行什么操作 直接使用即可
        httpSession.getServletContext();
        httpServletRequest.getServletContext();
        
        return null;
    }

    /**对于servletContext 我们如何获取呢?
     * 方案1: 使用request/session获取
     *         httpSession.getServletContext();
     *         httpServletRequest.getServletContext();
     * 方案2
     *    直接全局注入
     */

springmvc会在初始化容器的时候,讲servletContext对象存储到ioc容器中!

8、共享域对象操作

8.1 属性共享域回顾

在 JavaWeb 中,共享域指的是在 Servlet 中存储数据,以便在同一 Web 应用程序的多个组件中进行共享和访问。常见的共享域有四种:ServletContextHttpSessionHttpServletRequestPageContext

  1. ServletContext 共享域:ServletContext 对象可以在整个 Web 应用程序中共享数据,是最大的共享域。一般可以用于保存整个 Web 应用程序的全局配置信息,以及所有用户都共享的数据。在 ServletContext 中保存的数据是线程安全的。
  2. HttpSession 共享域:HttpSession 对象可以在同一用户发出的多个请求之间共享数据,但只能在同一个会话中使用。比如,可以将用户登录状态保存在 HttpSession 中,让用户在多个页面间保持登录状态。
  3. HttpServletRequest 共享域:HttpServletRequest 对象可以在同一个请求的多个处理器方法之间共享数据。比如,可以将请求的参数和属性存储在 HttpServletRequest 中,让处理器方法之间可以访问这些数据。(一次请求,多次转发,只有在服务器端跳转才有用)
  4. PageContext 共享域:PageContext 对象是在 JSP 页面Servlet 创建时自动创建的。它可以在 JSP 的各个作用域中共享数据,包括pageScoperequestScopesessionScopeapplicationScope 等作用域。
    共享域的作用是提供了方便实用的方式在同一 Web 应用程序的多个组件之间传递数据,并且可以将数据保存在不同的共享域中,根据需要进行选择和使用。

    setAttribute()
    getAttribute()

接收参数总结

相关推荐
hrrrrb25 分钟前
【Java Web 快速入门】十一、Spring Boot 原理
java·前端·spring boot
Java微观世界36 分钟前
Object核心类深度剖析
java·后端
MrSYJ40 分钟前
为什么HttpSecurity会初始化创建两次
java·后端·程序员
hinotoyk1 小时前
TimeUnit源码分享
java
AAA修煤气灶刘哥2 小时前
Java+AI 驱动的体检报告智能解析:从 PDF 提取到数据落地全指南
java·人工智能·后端
wxy3192 小时前
嵌入式LINUX——————TCP并发服务器
java·linux·网络
★YUI★2 小时前
学习游戏制作记录(玩家掉落系统,删除物品功能和独特物品)8.17
java·学习·游戏·unity·c#
微小的xx2 小时前
java + html 图片点击文字验证码
java·python·html
mask哥2 小时前
详解flink java基础(一)
java·大数据·微服务·flink·实时计算·领域驱动
克拉克盖博3 小时前
chapter03_Bean的实例化与策略模式
java·spring·策略模式