SpringMVC入门

发布于:2024-07-28 ⋅ 阅读:(130) ⋅ 点赞:(0)

目录

SpringMVC概述

SpringMVC快速入门

第一步:创建Maven工程,并导入相关的依赖

第二步:创建控制器类

第三步:初始化SpringMVC环境

第四步:创建Tomcat的Servlet容器配置类

第五步:导入tomcat插件,并设置war方式打包

第六步:启动

测试

注意:需要在main目录下面新建一个webapp目录 

请求路径优化

 指定请求方法

请求参数处理

六种常规类型

第一种:普通请求参数

第二种:pojo类型请求参数

第三种:数组类型请求参数

第四种:List集合类型

 第五种:map集合类型

日期请求参数传递

文件类型参数传递 

1.先导入依赖

2.编写文件解析器,并交给SringMVC管理(第三方bean)使用注解@Bean

 JSON类型参数传递

第一步:导入解析json对象的依赖

第二步:让SpringMVC开启辅助功能,如日期类型转换,json类型转换

第三步:编写Controller类,并使用注解@RequestBody,一个方法只能使用一次(解析前端传来的json对象)

​编辑 数组类型的pojo类型

处理中文请求乱码问题

 1.GET请求乱码问题

2.解决POST请求乱码

 响应数据

响应一个页面

响应JSON对象,也要使用@Response注解

响应JSON对象数组

RESful风格


SpringMVC概述

MVC(Model View Controller),一种用于创建web应用程序的表现层的模式

        1.Model(模型):数据模型,用于封装数据

        2.View(视图):页面视图,用于展示数据

  •                 jsp
  •                 html

        3.Controller(控制器):处理用户交互的调度器,用于根据用户需求处理程序逻辑

SpringMVC快速入门

第一步:创建Maven工程,并导入相关的依赖

springMVC的依赖

<!--        springMVC的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

servlet-api

注意:需要指定作用范围

<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
<!--            需要指定作用范围-->
            <scope>provided</scope>
        </dependency>

我们可以发现springMVC的依赖包括了spring-context的依赖

第二步:创建控制器类

/*
1.需要交给spring管理
2.定义处理请求的方法
3.设置当前方法的访问路径
4.设置返回数据类型为String
 */
@Controller
public class UserController {
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("user save");
        return "springMVC";
    }
}

 创建控制器类也需要四步:

第一步:需要交给spring管理,即添加@Controller注解

第二步:定义处理请求的方法-->public String save()

第三步:设置当前方法的访问路径-->使用注解@RequestMapping("/save")

第四步:设置返回数据类型为String-->使用注解@ResponseBody

第三步:初始化SpringMVC环境

 这是一个设置扫描范围的配置类(主配置类)

@Configuration
@ComponentScan("com.hhh")
public class SpringMvcConfig {
}

第四步:创建Tomcat的Servlet容器配置类

public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {
    //创建SpringMVC容器(spring容器)
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        //ApplicationContext ctx =new AnnotationConfigApplicationContext();
        //加载配置类,创建SpringMVC容器
        AnnotationConfigWebApplicationContext ctx =new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }
    //设置哪些请求交给springMVC管理
    @Override
    protected String[] getServletMappings() {
        //这里设置了所有请求都交给SpringMVC管理
        return new String[]{"/"};

    }
    //创建Spring容器
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }
}

第五步:导入tomcat插件,并设置war方式打包

 <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <!-- 指定端口 -->
                    <port>8080</port>
                    <!-- 请求路径 -->
                    <path>/</path>
<!--                    &lt;!&ndash;这个名称需要,在maven插件中显示应用名称&ndash;&gt;-->
<!--                    <server>tomcat7</server>-->
                </configuration>
            </plugin>
        </plugins>
    </build>
<packaging>war</packaging>

 完整pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hhh</groupId>
    <artifactId>spring_day6_MVC</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
<!--            需要指定作用范围-->
            <scope>provided</scope>
        </dependency>
<!--        springMVC的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <!-- 指定端口 -->
                    <port>8080</port>
                    <!-- 请求路径 -->
                    <path>/</path>
<!--                    &lt;!&ndash;这个名称需要,在maven插件中显示应用名称&ndash;&gt;-->
<!--                    <server>tomcat7</server>-->
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

第六步:启动

 点击加号,选择maven,然后再Run里填写tomcat7:run,最后点击apply

结果:

测试

启动成功

注意:需要在main目录下面新建一个webapp目录 

请求路径优化

添加一个新的类

@Controller
public class BookController {
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("book save");
        return "bookSpringMVC";
    }
}

请求路径与之前的一样,会报错

所以这样添加目录

但是这样子每个方法都要添加一级目录,比较麻烦,所以我们可以在这个类上使用注解@RequestMapping注解

@Controller
@RequestMapping("/book")
public class BookController {
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("book save");
        return "bookSpringMVC";
    }
}
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("user save");
        return "springMVC";
    }
}

测试:

 指定请求方法

现在我们使用的式@RequestMapping注解,这个注解支持GET,POST请求,但是我们要指定请求方法要怎么做呢?

@Controller
@RequestMapping("/book")
public class BookController {
    @RequestMapping(value = "/save",method = RequestMethod.GET)//这样子只能使用GET请求
    @ResponseBody
    public String save(){
        System.out.println("book save");
        return "bookSpringMVC";
    }
}

请求参数处理

六种常规类型

第一种:普通请求参数

请求参数的key值与方法的形参名一致

后端:

@Controller
public class ParamController {
    //普通类型参数
    @RequestMapping("/commonParam")
    @ResponseBody
    public String commonParam(@RequestParam("name") String username, Integer age){//请求参数名和变量名一致即可
        System.out.println("username="+username);
        System.out.println("age="+age);
        return "CommonParam";
    }

}

使用postman向后端发送请求

如果前端请求参数名字与后端形参名不一致时,使用@RequestParam注解。

SpringMVC会自动把String类型的age转换成Integer类型

第二种:pojo类型请求参数

pojo类的成员变量名字与前端的key值一致 

User类

public class User {
    private String name;
    private Integer age;
    private Address address;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
    

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }
}

 Address类型

public class Address {
    private String province;
    private String city;

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "Address{" +
                "province='" + province + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}

后端:
 

@Controller
public class ParamController {
  
    //pojo嵌套类型
    @RequestMapping("/pojoContainPojoParam")
    @ResponseBody
    public String pojoContainPojoParam(User user){
        System.out.println(user);
        return "pojoContainPojoParam";
  
}

前端:

可以发现如果成员变量也是pojo类型,就要使用成员变量名.成员变量名的方法

结果:

原理:SpringMVC会使用构造器实例化出一个pojo类对象,即User对象(new User()),然后使用User类里的setXxx()方法进行赋值,如果没有构造器会报错,没有set方法那么这个成员变量就为空null值

如果使用注解@RequestParam

就会报错:

因为@RequestParam是直接把请求参数与形参进行绑定,并直接赋值,这样一来User类型对象并没有实例化,所以就会报错

第三种:数组类型请求参数

前端使用多个相同名字的key值与形参变量名一致

@Controller
public class ParamController {
 
    //数组类型
    @RequestMapping("/arrayParam")
    @ResponseBody
    public String arrayParam(String[]list){
        System.out.println(Arrays.toString(list));
        return "arrayParam";
    }

}

 前端:

结果:

第四种:List集合类型

@Controller
public class ParamController {
    
    //集合类型
    @RequestMapping("/listParam")
    @ResponseBody
    public String listParam(@RequestParam List<String>list){
        //因为List不是简单类型,所以springMVC会直接把List看成pojo类型,然后会实例化list,但是List集合没有构造器,就会报错
        //所以添加@RequestParam注解,这样一来spring会直接给list赋值,而不是实例化去使用set()方法
        System.out.println(list);
        return "listParam";
    }
  
}

 前端:

可以发现我们后端的形参中使用了@RequestParam注解,因为这个注解的作用就是绑定形参变量,直接进行赋值,因为List集合不是简单类型,所以SpringMVC会把List集合看出pojo类型,会先实例化List集合再进行set方法赋值,但是List集合并没有构造器,因此不加@RequestParam注解就会报错:

 第五种:map集合类型

@Controller
public class ParamController {
    //map集合类型
    @RequestMapping("/mapParam")
    @ResponseBody
    public String mapParam(@RequestParam Map<String,String> map){
        //@RequestParam把请求参数与形参绑定,直接赋值
        //System.out.println(map);
        map.forEach((key,value)-> System.out.println(key+"->"+value));
        return "mapParam";
    }
}

前端:

结果:

日期请求参数传递

@Controller
public class DateController {
    @RequestMapping("/dateParam")
    @ResponseBody
    public String dateParam(Date date){
        System.out.println(date);
        return "dateParam";
    }
}

前端:

结果:

可以发现时期使用的是/来间隔,如果使用-来间隔,会报错:

不能把String类型转换成Date类型,所以我们要使用注解@DateTimeFormat的pattern属性来指定日期类型格式

@Controller
public class DateController {
    @RequestMapping("/dateParam")
    @ResponseBody
    public String dateParam(Date date,@DateTimeFormat(pattern = "yyyy-MM-dd") Date date1){
        System.out.println(date);
        System.out.println(date1);
        return "dateParam";
    }
}

如果要运行成功,还需要再主配置类中添加@EnableWebMvc,让SpringMVC开启辅助功能

@Configuration
@ComponentScan("com.hhh")
@EnableWebMvc//让SpringMVC开启辅助功能
public class SpringMvcConfig {
}

结果:

文件类型参数传递 

1.先导入依赖

<!--        文件解析的依赖-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>

2.编写文件解析器,并交给SringMVC管理(第三方bean)使用注解@Bean

@Configuration
@ComponentScan("com.hhh")
@EnableWebMvc//让SpringMVC开启辅助功能
public class SpringMvcConfig {
    //配置文件解析器,并交给SpringMVC管理
    @Bean("multipartResolver")//这个解析器类型的Bean id必须是multipartResolver,源码是通过id名来获取bean的
    public MultipartResolver multipartResolver(){
        CommonsMultipartResolver commonsMultipartResolver=new CommonsMultipartResolver();
        commonsMultipartResolver.setMaxUploadSize(1024*1024);//单位是字节(byte)
        //设置文件最大为1MB
        return  commonsMultipartResolver;
    }
}

 注意:这个解析器类型的Bean id必须是multipartResolver,源码是通过id名来获取这个类型的bean

后端

@Controller
public class FileController {
    @RequestMapping("/fileParam")
    @ResponseBody
    public String fileParam(MultipartFile file) throws IOException {
        if(!file.isEmpty()){
            file.transferTo(new File("D://test.txt"));//把文件另存为
        }
        return "fileParam";
    }
}

前端

 请求方法只能选择post,文件类型要选择form-data,其他类型选择的是右边那个长的

结果:
D盘出现该文件,成功

 JSON类型参数传递

第一步:导入解析json对象的依赖

<!--        解析json的依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>

第二步:让SpringMVC开启辅助功能,如日期类型转换,json类型转换

@Configuration
@ComponentScan("com.hhh")
@EnableWebMvc//让SpringMVC开启辅助功能,如日期类型转换,json类型转换
public class SpringMvcConfig {
    //配置文件解析器,并交给SpringMVC管理
    @Bean("multipartResolver")//这个解析器类型的Bean id必须是multipartResolver,源码是通过id名来获取bean的
    public MultipartResolver multipartResolver(){
        CommonsMultipartResolver commonsMultipartResolver=new CommonsMultipartResolver();
        commonsMultipartResolver.setMaxUploadSize(1024*1024);//单位是字节(byte)
        //设置文件最大为1MB
        return  commonsMultipartResolver;
    }
}

第三步:编写Controller类,并使用注解@RequestBody,一个方法只能使用一次(解析前端传来的json对象)

@Controller
public class JsonController {
    @RequestMapping("/pojoParamForJson")
    @ResponseBody
    public String pojoParamForJson(@RequestBody User user){
        System.out.println(user);
        return "pojoParamForJson";
    }
}

前端

 

结果:

 数组类型的pojo类型

   @RequestMapping("/arrayPojoParam")
    @ResponseBody
    public String arrayPojoParam(@RequestBody List<User>list){
        System.out.println(list);
        return "arrayPojoParam";
    }

前端

数组使用[]

结果

处理中文请求乱码问题

 1.GET请求乱码问题

   <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <!-- 指定端口 -->
                    <port>8080</port>
                    <!-- 请求路径 -->
                    <path>/</path>
<!--                    &lt;!&ndash;这个名称需要,在maven插件中显示应用名称&ndash;&gt;-->
<!--                    <server>tomcat7</server>-->
                    <uriEncoding>utf-8</uriEncoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

添加<uriEncoding>utf-8</uriEncoding>

2.解决POST请求乱码

为web容器添加过滤器并指定字符集

public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {
    //创建SpringMVC容器(spring容器)
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        //ApplicationContext ctx =new AnnotationConfigApplicationContext();
        //加载配置类,创建SpringMVC容器
        AnnotationConfigWebApplicationContext ctx =new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }
    //设置哪些请求交给springMVC管理
    @Override
    protected String[] getServletMappings() {
        //这里设置了所有请求给SpringMVC管理
        return new String[]{"/"};
    }
    //创建Spring容器
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    //设置参数编码为utf-8,解决post请求乱码
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        return new Filter[]{characterEncodingFilter};
    }
}

 添加
    //设置参数编码为utf-8,解决post请求乱码
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        return new Filter[]{characterEncodingFilter};
    }

 响应数据

响应一个页面

创建一个jsp文件

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<div>hello</div>
</body>
</html>
@Controller
public class ResponseController {
    //不加@ResponseBody就会去找页面名为page.jsp的页面
    @RequestMapping("/toPage")
    public String toPage(){
        System.out.println("toPage");
        return "page.jsp";
    }
}

如果加了@ResponseBody

 @RequestMapping("/toText")
    @ResponseBody
    public String toText(){
        System.out.println("toText");
        return "page.jsp";
    }

返回的就是字符串本身

 所以@Response注解(使用在方法上)的作用就是设置当前控制器的返回值作为响应体。

不加这个注解就会去找对应名字的页面,并返回给前端 

响应JSON对象,也要使用@Response注解

返回类型是对象

@Controller
public class ResponseController {

    @RequestMapping("/toJson")
    @ResponseBody
    public User toJson(){
        User user = new User();
        user.setName("hhh");
        user.setAge(19);
        Address address = new Address();
        address.setProvince("河北");
        address.setCity("石家庄");
        user.setAddress(address);
        return user;
    }


}

 

响应JSON对象数组

@Controller
public class ResponseController {

    @RequestMapping("/toJsonArray")
    @ResponseBody
    public List<User> toJsonArray(){
        User user1 = new User();
        user1.setName("hhh");
        user1.setAge(19);
        Address address = new Address();
        address.setProvince("河北");
        address.setCity("石家庄");
        user1.setAddress(address);

        User user2 = new User();
        user2.setName("aaa");
        user2.setAge(19);
        Address address2 = new Address();
        address2.setProvince("河北");
        address2.setCity("石家庄");
        user2.setAddress(address2);
        List<User>list=new ArrayList<>();
        Collections.addAll(list,user1,user2);
        return list;

    }

}

 

注意:跟解析请求JSON对象一样,也要导入json解析所需要的依赖,也需要使用注解@EnableWebMvc//让SpringMVC开启辅助功能,如日期类型转换,json类型转换

RESful风格

@Controller
public class UserController {
    //新增,保存操作
    @RequestMapping(value = "/users",method = RequestMethod.POST)
    @ResponseBody
   public String save(){
       return "save";
   }
   //修改,更新
   @RequestMapping(value = "/users",method = RequestMethod.PUT)
   @ResponseBody
   public String update(){
        return "update";
   }
   //查询全部
    @RequestMapping(value = "/users",method = RequestMethod.GET)
    @ResponseBody
    public String getAll(){
        return "getAll";
    }
    //查询某一个
    @RequestMapping(value = "/users/{id}",method = RequestMethod.GET)
    @ResponseBody
    public String getById(@PathVariable("id") Integer id){//通过请求路径获取值,而不是通过请求参数
        System.out.println("id="+id);
        return "getById";
    }
    //删除某一个
    @RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable("id") Integer id){
        System.out.println("id="+id);
        return "delete";
    }
}

我们可以发现每个@RequestMapping都要写/users,比较麻烦,我们可以直接在类上使用注解 @RequestMapping

每个方法都要写@Response比较麻烦,我们可以直接在类上使用注解 @ResponseBody

@Controller
@RequestMapping("/users")
@ResponseBody
public class UserController {
    //新增,保存操作
    @RequestMapping(method = RequestMethod.POST)
   public String save(){
       return "save";
   }
   //修改,更新
   @RequestMapping(method = RequestMethod.PUT)
   public String update(){
        return "update";
   }
   //查询全部
    @RequestMapping(method = RequestMethod.GET)
    public String getAll(){
        return "getAll";
    }
    //查询某一个
    @RequestMapping(value = "/{id}",method = RequestMethod.GET)
    public String getById(@PathVariable("id") Integer id){//通过请求路径获取值,而不是通过请求参数
        System.out.println("id="+id);
        return "getById";
    }
    //删除某一个
    @RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
    public String delete(@PathVariable("id") Integer id){
        System.out.println("id="+id);
        return "delete";
    }
}

然后我们还发现每个@RequsetMapping都要写一个method属性来指定请求方法,比较麻烦,所以,Post请求就使用@PostMapping,以此类推

@ResponseBody和@Controller这两个注解放在一起可以使用@RestController注解来替代


//@Controller
//@ResponseBody
@RestController
@RequestMapping("/users")
public class UserController {
    //新增,保存操作
    //@RequestMapping(method = RequestMethod.POST)
    @PostMapping
   public String save(){
       return "save";
   }
   //修改,更新
   //@RequestMapping(method = RequestMethod.PUT)
    @PutMapping
   public String update(){
        return "update";
   }
   //查询全部
   // @RequestMapping(method = RequestMethod.GET)
    @GetMapping
    public String getAll(){
        return "getAll";
    }
    //查询某一个
    //@RequestMapping(value = "/{id}",method = RequestMethod.GET)
    @GetMapping("/{id}")
    public String getById(@PathVariable("id") Integer id){//通过请求路径获取值,而不是通过请求参数
        System.out.println("id="+id);
        return "getById";
    }
    //删除某一个
    //@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
    @DeleteMapping("/{id}")
    public String delete(@PathVariable("id") Integer id){
        System.out.println("id="+id);
        return "delete";
    }
}

@Configuration
public class SpringWebSupport extends WebMvcConfigurationSupport {
    //设置静态资源不走SpringMvc控制器
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
    }
}