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()

接收参数总结

相关推荐
ProtonBase17 分钟前
如何从 0 到 1 ,打造全新一代分布式数据架构
java·网络·数据库·数据仓库·分布式·云原生·架构
乐之者v23 分钟前
leetCode43.字符串相乘
java·数据结构·算法
suweijie7684 小时前
SpringCloudAlibaba | Sentinel从基础到进阶
java·大数据·sentinel
公贵买其鹿4 小时前
List深拷贝后,数据还是被串改
java
xlsw_7 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹8 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭9 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫9 小时前
泛型(2)
java
超爱吃士力架9 小时前
邀请逻辑
java·linux·后端
南宫生9 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论