SpringMVC学习记录

SpringMVC简介与配置

SpringMVC是一种基于Java实现MCV模型的轻量级Web框架,我们该如何使用呢?
首先在Maven中添加坐标

 	<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.3.3.RELEASE</version>
    </dependency>

随后我们创建一个SpringMVC的配置文件,该文件只负责声明这是SpringMVC的配置,并扫描对应的controller层。

package configs;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
//创建SpringMVC的配置文件,加载需要的Bean
@ComponentScan("controller")
public class SpringMvcConfig {
}

在配置完后如何让Tomcat启动时加载呢,我们先前加载Spring的方式是通过AnnotationConfigApplicationContext来生成的,但在Web项目中要使用AnnotationConfigWebApplicationContext来生成。其通过继承AbstractDispatcherServletInitializer这个类来实现,并且需要重写下面的三个方法来分别做SpringMVC、数据请求以及Spring的配置。

package configs;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

public  class ServletConfig extends AbstractDispatcherServletInitializer {
    //加载SpringMVC配置
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        //在Spring中,使用AnnotationConfigApllication来创建Spring容器,但Web环境下要使用下面的
        AnnotationConfigWebApplicationContext ctx=new AnnotationConfigWebApplicationContext();
        //上面是一个空的容器,使用register来加载SpringMVC的配置
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }
    //设置哪些请求归属SpringMVC处理
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};//代表所有请求都要交给SpringMVC去处理
    }
    //加载Spring容器配置
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext ctx=new AnnotationConfigWebApplicationContext();
        //上面是一个空的容器,使用register来加载SpringMVC的配置
        ctx.register(SpringConfig.class);
        return ctx;
    }
}

当然我们也可以使用下面的代码来简化开发,只不过相较于上面的配置我们不知道具体是如何实现的而已。

在这里插入图片描述

随后我们定义Controller

package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
    @RequestMapping("/save")
    @ResponseBody//将返回的信息作为整体相应内容
    public String save(){
        System.out.print("controller..");
        return "{mode:ok}";
    }
}

我们分析一下这个案例的工作流程。

在这里插入图片描述

Spring加载控制

SpringMVC负责加载Controller中的Bean,而Spring则应该只负责加载业务层(service),数据层(dao)的Bean,那么如何让Spring不重复加载SpringMVC负责的Bean呢?
一种方式是精确定位,即在Spring扫描时只写service、dao等,那么自然也就不会加载Controller的类了
另一种则是排除,在扫描时,依旧扫描全部包,但排除一部分,如Controller的包。

在这里插入图片描述

PostMan工具

这是一款可以模拟http请求的插件,可以方便我们开发。PostMan下载地址如下

https://www.postman.com/downloads/

下载后我们需要创建一个账号,随后我们创建一个工作空间,然后写入请求就可以模拟了。

在这里插入图片描述

SpringMVC开发Controller

请求映射路径

package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/users")
public class UserController {
    @RequestMapping("/save")
    @ResponseBody//将返回的信息作为整体相应内容
    public String save(){
        System.out.print("controller..");
        return "{mode:usersave}";
    }
}

不同于Servlet的doGet与doPost方法,SpringMVC的后端代码是不区分GetPost的,因此我们只需要在PostMan中选择不同的提交形式即可。

在这里插入图片描述

然而,我们在实验过程中,如果传递的参数是汉字的话,则会出现乱码问题:{mode:彭祥}
该如何解决呢?在原本的Servlet中我们采用过滤器的方式解决乱码问题,在SpringMVC中亦是如此,那么该如何实现呢,我们在ServletConfig中重写getServletFilters()方法。

package configs;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
import javax.servlet.Filter;
public  class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringConfig.class};
    }
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter filter=new CharacterEncodingFilter();
        filter.setEncoding("UTF-8");
        return new Filter[]{filter};
    }
}

Controller中的传参代码如下:参数为name,而发送http请求的是:
在这里插入图片描述
需要注意的是,SpringMVC能够将http传递的参数与形参相同时进行映射。

package controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/users")
public class UserController {
    @RequestMapping("/save")
    @ResponseBody//将返回的信息作为整体相应内容
    public String save(String name){
        System.out.print("name:"+name+"\ncontroller..");
        return "{mode:"+name+"}";
    }
}

然后,如何http请求的参数与形参不同,则无法映射,从而会导致传参失败。报400错误。

在这里插入图片描述

那么此时该如何映射呢,使用@RequestParam注解即可

 public String save(@RequestParam("username") String name){
        System.out.print("name:"+name+"\ncontroller..");
        return "{mode:"+name+"}";
    }

那么如果形参是一个对象呢?如下Users对象

package domain;

public class Users {
    private int id;
    private String name;
    private String password;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
public String save(Users user){
        System.out.print("name:"+user.getName()+"\ncontroller..");
        return "{mode:"+user.getName()+"}";
    }

此时发送请求依旧成功。
在这里插入图片描述
那如果对于一些类里面嵌套类的情况呢?

在这里插入图片描述
后端代码不变,但http发送的请求参数需要改变:类名.属性名

?name=peng&password=1234&address.city=city

JSON格式传递参数

首先导入JSON坐标:

<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
</dependency>

由于SpringMVC是不支持JOON格式接收的,要想使其支持,我们需要在SpringMVC文件中开启@EnableWebMvc注解,即开启自动转换JSON数据的支持。

package configs;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
//创建SpringMVC的配置文件,加载需要的Bean
@ComponentScan("controller")
@EnableWebMvc
public class SpringMvcConfig {
}

随后我们运行发现SpringMVC将接收的List数组当对象了去构建了,导致报错,此时在List前加上@RequestBody注解即可,注意,此时不能加@RequestParm,因为此时数据是封装在JSON中的。

@RequestMapping("jsonlist")
    @ResponseBody
    public String jsonList(@RequestBody List<String> likes){
        System.out.print(likes);
        return "0";
    }

注意JSON数据的封装测试类型。

 @RequestMapping("jsonlist")
    @ResponseBody
    public String jsonList(@RequestBody List<String> likes){
        System.out.print(likes);
        return "0";
    }

在这里插入图片描述

  @RequestMapping("jsonpojo")
    @ResponseBody
    public String jsonPOJO(@RequestBody Users user){
        System.out.print(user);
        return "{user:"+user+"}";
    }

在这里插入图片描述

@RequestMapping("jsonpojolist")
    @ResponseBody
    public String jsonPOJOList(@RequestBody List<Users> users){
        System.out.print(users);
        return "{user:"+users+"}";
    }

在这里插入图片描述

日期型类型参数传递

在这里插入图片描述
在这里插入图片描述

还记得@EnableWebMvc注解吗,这个注解在格式转换中具有非常多的应用。
事实上我们前面所提到的JSON数据转换并不是真正的JSON数据,其只是一个字符串而已。真正要返回JSON格式的对象怎么做呢,很简单,只需要将返回值类型改为对应的对象类型即可。

 @RequestMapping("jsonpojo")
    @ResponseBody
    public Users jsonPOJO(@RequestBody Users user){
        System.out.print(user);
        return user;
    }
    @RequestMapping("jsonpojolist")
    @ResponseBody
    public List<Users> jsonPOJOList(@RequestBody List<Users> users){
        System.out.print(users);
        return users;
    }

在这里插入图片描述

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-26 07:00:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-26 07:00:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-26 07:00:03       87 阅读
  4. Python语言-面向对象

    2024-03-26 07:00:03       96 阅读

热门阅读

  1. 自动驾驶技术的应用场景和限制

    2024-03-26 07:00:03       41 阅读
  2. Android 8.1 不可安装应用

    2024-03-26 07:00:03       39 阅读
  3. 无线网络与物联网

    2024-03-26 07:00:03       38 阅读
  4. Sentinel

    Sentinel

    2024-03-26 07:00:03      39 阅读
  5. Qt实现TFTP Server和 TFTP Client(二)

    2024-03-26 07:00:03       32 阅读
  6. AcWing 1015. 摘花生

    2024-03-26 07:00:03       45 阅读
  7. Ubuntu 安装Docker 和 Docker Compose

    2024-03-26 07:00:03       35 阅读
  8. Spark SQL

    Spark SQL

    2024-03-26 07:00:03      39 阅读
  9. 面试算法-102-LRU 缓存

    2024-03-26 07:00:03       40 阅读