SpringMVC基础学习

SpringMVC基础学习

1. SpringMVC简介

  • SpringMVC技术与Servlet技术功能等同,均属于web层开发技术
  • SpringMVC是一种基于Java实现的MVC模型的轻量级web框架
    • 优点:使用简单,开发便捷,灵活性强

  • 基本使用:

    • 导入SpringMVC坐标与Servlet坐标
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.22.RELEASE</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    
    • 创建SpringMVC控制器类(等同于Servlet功能)
      • @COntroller:SpringMVC控制器类,设定SpringMVC的核心控制器bean
      • @ResponseBody:设置当前控制器方法响应内容为当前返回值,无需解析
      • @RequestMapping:设置当前控制器方法请求访问路径
    @Controller
    public class UserController {
        @RequestMapping("/save")
        @ResponseBody
        public String save(String str){
            System.out.println("UserController save doing ...");
            return "{'model:'springmvc'}";
        }
    }
    
    • 初始化SpringMVC环境(同Spring环境),设定SpringMVC加载对应的bean
    @Configuration
    @ComponentScan({"com.cqut.controller"})
    public class SpringMVCConfig {
    }
    
    • 初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求
      • AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类
      • createServletApplicationContext()方法,创建Servlet容器时,SpringMVC类型的bean被注册,进而加载由SpringMVCConfig配置中所有的bean,放入WebApplicationContextt对象范围中
      • WebApplicationContext的作用范围为ServletContext范围,即整个web容器范围
    public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {
        protected WebApplicationContext createServletApplicationContext() {
            //这里需要和Spring中加载配置文件做区分
            AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
            context.register(SpringMVCConfig.class);
            return context;
        }
        protected String[] getServletMappings() {
            //拦截对应请求进行请求响应
            return new String[]{"/"};
        }
        protected WebApplicationContext createRootApplicationContext() {
            return null;
        }
    }
    

可能出现问题:

spring-webmvc 5.3出现javax.servlet.http.HttpServletResponse.setContentLengthLong(J)V报错

说明:这里导入的spring-webmvc的是5.3版本的抛出异常,需要将版本降低到5.3版本一下,就没有异常了。

注意:tomcat是对war包进行运行,jar包并不能执行

2. 工作流程

2.1. 服务器启动初始化过程

  1. 服务器启动,执行ServletContainerInitConfig类,初始化web容器
  2. 执行createServletApplicationContext方法,创建WebApplicationContext对象
  3. 加载SpringMVCConfig
  4. 执行@ComponentScan加载对应的bean
  5. 加载UserController,每个@RequestMapping的名称对应一个具体的方法
  6. 执行getServletMapping方法,定义所有请求都通过SpringMVC

2.2 单次请求过程

  1. 发送请求
  2. web容器发现所有请求都经过SpringMVC,将请求交给SpringMVC处理
  3. 解析请求路径/save
  4. 由/save匹配执行对应的方法save()
  5. 执行save()
  6. 检测到有@ResponseBody直接将save()方法的返回值作为响应体返回给请求方

3. Bean加载控制

3.1. 控制范围

  • SpringMVC控制bean:controller(表现层)
    • SpringMVC加载的bean对应的包均在com.cqut.controller包内
  • Spring控制bean:service(业务层)功能(DataSource等)
    • 方式一:Spring加载的bean设定扫描范围为com.cqut,排除controller包内的bean
    • 方式二:Spring加载的bean设定扫描范围为精准范围,例如service包,dao包等
    • 方式三:不区分Spring与SpringMVC的环境,加载到同一环境中

3.2. 代码实现

  • 方式一:

    @ComponentScan({"com.cqut.controller"})
    public class SpringMvcConfig {
    }
    
    @Configuration
    @ComponentScan(value = "com.cqut",
        excludeFilters = @ComponentScan.Filter(
                type = FilterType.ANNOTATION,
                classes = Controller.class
        )
    )
    public class SpringConfig {
    }
    
    • excludeFilters:排除扫描路径中加载的bean,需要指定类别(type)与具体相(classes)
    • includeFilters:加载指定bean,需要指定类别(type)与具体相(classes)
    • 这种方式下,不能在SpringMvcConfig加上注解@Configuration,否则依旧会扫描到controller
  • 方式二:

    @Configuration
    @ComponentScan({"com.cqut.controller"})
    public class SpringMvcConfig {
    }
    
    @Configuration
    @ComponentScan({"com.cqut.dao", "com.cqut.service"})
    public class SpringConfig {
    }
    

3.3. 简化开发

  • 将继承AbstractDispatcherServletInitializer这个类替换为其子类
public class ServletContainerInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {

    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

4. 请求与响应

4.1. 请求映射路径

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/save")
    @ResponseBody
    public String save(String str){
        System.out.println("UserController save doing ...");
        return "{'model:'springmvc'}";
    }
}
  • @RequestMapping
    • 类型:方法注解,类注解
    • 设置当前控制器方法请求访问路径,如果设置在类上同一设置当前控制器方法请求访问路径前缀

4.2. 请求参数

  • Get方法传参接收
    • url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数

    @RequestMapping("/save0")
    @ResponseBody
    public String save0(String username, String password, Integer age){
        System.out.println("Username = " + username);
        System.out.println("Password = " + password);
        System.out.println("Age = " + age);
        return "Get:{'model:'springmvc'}";
    }
  • Post请求传参接收
    • form表单post请求传参,表单参数名与形参变量名相同,定义形参即可接收参数

    @RequestMapping("/save1")
    @ResponseBody
    public String save1(String username, String password, Integer age){
        System.out.println("Username = " + username);
        System.out.println("Password = " + password);
        System.out.println("Age = " + age);
        return "Post:{'model:'springmvc'}";
    }
  • 处理Post请求参数中文乱码
    • 为web容器添加过滤器并指定字符集,Spring-web包中提供了专用的字符过滤器
    • 可以设置多个过滤器
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter filter1 = new CharacterEncodingFilter();
        filter1.setEncoding("utf-8");
        return new Filter[]{filter1};
    }
  • 五种参数传参处理

    • 普通参数:url地址传参,地址参数名和形参变量名相同,定义形参即可接收参数
      • @RequestParam:形参注解,绑定请求参数与处理器方法形参间的关系。当请求中参数名与处理器方法形参名称不一致的,进行绑定

        @RequestMapping("/save2")
        @ResponseBody
        public String save2(@RequestParam("username") String name, String password, Integer age){
            System.out.println("Username = " + name);
            System.out.println("Password = " + password);
            System.out.println("Age = " + age);
            return "Post:{'model:'springmvc'}";
        }
    
    • POJO类型参数:请求参数名与新参对象属性名相同,定义POJO形参即可接收参数

        @RequestMapping("/save3")
        @ResponseBody
        public String save3(User user){
            System.out.println(user);
            return "Post:{'model:'springmvc'}";
        }
    
  • 嵌套POJO类型参数:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数

        @RequestMapping("/save6")
        @ResponseBody
        public String save6(Account account){
            System.out.println(account);
            return "Post:{'model:'springmvc'}";
        }
    
    @Data
    public class Account {
        private String num;
        private User user;
    }
    
  • 数组类型参数:请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型形参即可接收参数

        @RequestMapping("/save4")
        @ResponseBody
        public String save4(String[] courses){
            System.out.println(Arrays.toString(courses));
            return "Post:{'model:'springmvc'}";
        }
    
  • 集合类型参数:请求参数与形参对象名相同且相同且请求参数为多个,@RequestParam绑定参数关系

        @RequestMapping("/save5")
        @ResponseBody
        public String save5(@RequestParam List<String> courses){
            System.out.println(courses);
            return "Post:{'model:'springmvc'}";
        }
    
4.2.1 json传递参数(重点 常用)

@RequestBody@RequestParam区别:

  • @RequestParam用于接收url地址传参,表单传参[application/x-www-form-urlencoded]
  • @RequestBody用于接收json数据[application/json]
  • 后期开发中,发送json格式数据为主,@RequestBody应用较广,如果发送非json格式数据,选用@RequestParam接收请求参数

操作演示:

  • 处理Json格式依赖坐标如下:(提供数据转换的功能)
    • 这里需要注意jdk和导入坐标版本兼容性问题
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.0</version>
</dependency>
  • 开启数据转换的功能
@Configuration
@ComponentScan({"com.cqut.controller"})
@EnableWebMvc
public class SpringMvcConfig {
}
  • 普通数组传参

    @RequestMapping("/save0")
    @ResponseBody
    public String save0(@RequestBody List<String> courses){
        System.out.println(courses);
        return "{'model':'array for json param'}";
    }
  • 对象(嵌套对象)传参

    @RequestMapping("/save1")
    @ResponseBody
    public String save1(@RequestBody Account account){
        System.out.println(account);
        return "{'model':'pojo for json param'}";
    }
  • 集合对象传参

    @RequestMapping("/save2")
    @ResponseBody
    public String save2(@RequestBody List<User> users){
        System.out.println(users);
        return "{'model':'list for json param'}";
    }

4.3. 日期类型参数传递

  • 日期类型数据基于系统不同格式也不同,在接受形参时,根据不同的日期格式设置不同的接收方式

    @RequestMapping("/save3")
    @ResponseBody
    public String save3(Date date1,
                        @DateTimeFormat(pattern = "yyyy-MM-dd") Date date2,
                        @DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss") Date date3){
        System.out.println(date1);
        System.out.println(date2);
        System.out.println(date3);
        return "{'model':'data param show'}";
    }
  • @DataTimeFormat:设定日期时间数据格式。Pattern属性:日期时间格式字符串
  • Converter接口(类型转换器):有多个实现类来实现各种数据的格式转换
package org.springframework.core.convert.converter;
import org.springframework.lang.Nullable;
@FunctionalInterface
public interface Converter<S, T> {
    @Nullable
    T convert(S var1);
}

4.4. 响应json数据

  • 响应页面
  • 响应数据
    • 文本数据
    • json数据
    @RequestMapping("/index")
    @ResponseBody
    public List<User> save7(){
        List<User> users = new ArrayList<User>();
        User user1 = new User();
        user1.setPassword("123");
        user1.setUsername("xln");
        user1.setAge(12);
        users.add(user1);
        User user2 = new User();
        user2.setPassword("1313");
        user2.setUsername("xln");
        user2.setAge(20);
        users.add(user2);
        return users;
    }

  • HttpMessageConverter接口(将数据转换成json格式)
public interface HttpMessageConverter<T> {
    boolean canRead(Class<?> var1, @Nullable MediaType var2);

    boolean canWrite(Class<?> var1, @Nullable MediaType var2);

    List<MediaType> getSupportedMediaTypes();

    T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;

    void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
}

4.5. REST风格

  • REST(Representational State Transfer),表现形式状态转换
    • 优点:隐藏资源的访问行为,无法通过地址得知对资源是何种操作
请求方式操作REST快速开发
GET查询@GetMapping
POST新增/保存@PostMapping
PUT修改/更新@PutMapping
DELETE删除@DeleteMapping
参数注解来源
@RequestParam用于接收url地址传参或表单传参
@RequestBody用于接收json数据
@PathVariable用于接收路径参数,使用{参数名称}描述路径参数
  • @RestController:设置当前控制器类为RESTful风格,等同于@Controller@ResponseBody两个注解组合功能

4.6. 放行静态资源访问

@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/html/**").addResourceLocations("/html/");
    }
}
  • 当访问/xx/**,走/xx/目录下的内容
  • 注意这里是从webapp目录下走的,文件夹命名一定要是webapp

4.6. 放行静态资源访问

@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/html/**").addResourceLocations("/html/");
    }
}
  • 当访问/xx/**,走/xx/目录下的内容
  • 注意这里是从webapp目录下走的,文件夹命名一定要是webapp

在这里插入图片描述

  • 同时SpringMvcSupport这个配置类一定要是SpringMvc这个类通过包扫描进行加载(试过其他各种加载都没加载上,原因未知)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值