SpringMVC学习笔记(一)- 请求与响应

SpringMVC学习笔记(一)- 请求与响应

SpringMVC环境搭建及工作原理描述

  • 使用SpringMVC技术需要先导入SpringMVC坐标与Servlet坐标

    <!-- 导入坐标springmvc 与 servlet -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
    
  • 创建SpringMVC控制器类(与Servlet功能等效)

    /**
     * 1.定义Controller
     * 2.使用@Controller 定义 bean
     */
    @Controller
    public class UserController {
    
        //设置当前操作的访问路径
        @RequestMapping("/save")
        //设置当前操作的返回类型
        @ResponseBody
        public String save(){
            System.out.println("user save ...");
            return "{'module':'springmvc'}";
        }
    }
    
  • 初始化SpringMVC(同Spring环境),设定SpringMVC加载对应的bean

    //创建springmvc的配置文件,加载controller对应的bean
    @Configuration
    @ComponentScan("com.itheima.controller")
    public class SpringMvcConfig {
    }
    
  • 初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求(注意要在pom.xml文件导入tomcat坐标,同时添加tomcat的插件)

    //定义一个servlet容器启动的配置类,在里面加载spring的配置
    public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    
        //加载springMVC容器配置
        protected WebApplicationContext createServletApplicationContext() {
            AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
            ctx.register(SpringMvcConfig.class);
            return ctx;
        }
    
        //设置哪些请求归属SpringMVC处理
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
    
        //加载spring容器配置
        protected WebApplicationContext createRootApplicationContext() {
            return null;
        }
    }
    

启动服务器初始化过程

  • 服务器启动,执行ServletContainersInitConfig类,初始化web容器;
  • 执行createServletApplicationContext方法,创建了WebApplicationContext对象
  • 加载SpringMvcConfig
  • 执行@ComponentScan加载对应的bean
  • 加载UserController,每个@RequestMapping的名称对应一个具体的方法
  • 执行getServletMappings方法,定义所有的请求都通过SpringMVC
    在这里插入图片描述

单次请求过程

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

Bean加载控制

问题引入:因为功能不同,如何避免Spring错误的加载到SpringMVC的bean
解决方案

  • 类注解方式:

    //创建springmvc的配置文件,加载controller对应的bean
    /**
     * excludeFilters:排除扫描路径中加载的bean,需要指定类别(type)与具体项(classes)
     * includeFilters:加载指定的bean,需要指定类别(type)与具体项(classes)
     */
    @Configuration
    @ComponentScan(value="com.itheima.controller",
    	excludeFilters=@ComponentScan.Filter(
    		type=FilterType.ANNOTATION,
    		classes=Controller.class
    	)
    )
    public class SpringConfig {
    }
    
  • bean的加载格式

    //定义一个servlet容器启动的配置类,在里面加载spring的配置
    public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    
        //加载springMVC容器配置
        protected WebApplicationContext createServletApplicationContext() {
            //初始化WebApplicationContext对象
            AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
            //加载指定配置类
            ctx.register(SpringMvcConfig.class);
            return ctx;
        }
    
    	//加载spring容器配置
        protected WebApplicationContext createRootApplicationContext() {
            //初始化WebApplicationContext对象
            AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
            //加载指定配置类
            ctx.register(SpringConfig.class);
            return ctx;
        }
    
        //设置哪些请求归属SpringMVC处理
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
    }
    
  • 简化开发

    public class ServletContainersInitConfig extends AbstractAnnotationDispatcherServletInitializer {
    
        protected Class<?>[] getServletConfigClasses() {
    		return new Class[]{SpringMvcConfig.class};
    	}
    	
    	protected Class<?>[] getRootConfigClasses() {
    		return new Class[]{SpringConfig.class};
    	}
    	
    	protected String[] getServletMappings() {
    		return new String[]{"/"};
    	}
    }
    

请求与响应

请求映射路径

  • 团队多人开发,由于每个人设置不同的请求路径会出现冲突路径,提出设置模块名作为请求路径前缀
  • 解决方案:设置当前控制器方法请求访问路径,如果设置在类上统一设置当前控制器方法请求访问路径前缀
    @RequestMapping("/book")
    @Controller
    public class BookController {
    
        @RequestMapping("/save")
        @ResponseBody
        public String save(){
            System.out.println("book save ...");
            return "{'module':'save'}";
        }
    }
    

参数传递类型

普通参数

GET请求

  • 在对应Controller类中的函数添加参数
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        //设置当前操作的访问路径
        @RequestMapping("/save")
        //设置当前操作的返回类型
        @ResponseBody
        public String save(String name,String age){
            System.out.println("username:"+name+", age:"+age);
            return "{'module':'springmvc'}";
        }
    }
    
  • 普通参数:url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数
    在这里插入图片描述

POST请求

  • 普通参数:form表单post请求形参,表单参数与形参变量名相同,定义形参即可接收参数
    在这里插入图片描述

  • 在对应Controller类中的函数添加参数

    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        //设置当前操作的访问路径
        @RequestMapping("/save")
        //设置当前操作的返回类型
        @ResponseBody
        public String save(String name,String age){
            System.out.println("username:"+name+", age:"+age);
            return "{'module':'springmvc'}";
        }
    }
    
  • 【注意】:Post请求中文乱码处理方法
    ServletContainersInitConfig类中,复写getServletFilters函数。为web容器添加过滤器并指定字符集,Spring-web包中提供了专用的字符过滤器

    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("utf-8");
        return new Filter[]{filter};
    }
    

普通参数请求参数名与形参数名不同的情况,我们通常可以用@RequestParam解决

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

    //设置当前操作的访问路径
    @RequestMapping("/save")
    //设置当前操作的返回类型
    @ResponseBody
    public String save(@RequestParam("name") String username, String age){
        System.out.println("username:"+username+", age:"+age);
        return "{'module':'springmvc'}";
    }
}

POJO类型参数
  • 请求参数名与形参属性名相同,定义POJO类型形参即可接收参数
  • 在对应Controller中的函数添加pojo参数
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        //设置当前操作的访问路径
        @RequestMapping("/save")
        //设置当前操作的返回类型
        @ResponseBody
        public String save(User user){
            System.out.println("pojo参数传递" + user);
            return "{'module':'springmvc'}";
        }
    }
    
  • POST MAN 接口测试
    在这里插入图片描述
嵌套POJO类型参数
  • 嵌套POJO参数:POJO对象中包含POJO对象
    public class User {
    
        private String name;
        private int age;
    
        private Address address;//嵌套的对象
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", address=" + address +
                    '}';
        }
    }
    
  • POST MAN 接口测试
    在这里插入图片描述
数组类型参数
  • 请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型形参即可接收参数
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        //设置当前操作的访问路径
        @RequestMapping("/save")
        //设置当前操作的返回类型
        @ResponseBody
        public String save(String[] hobbies){
            System.out.println("数组参数传递" + Arrays.toString(hobbies));
            return "{'module':'springmvc'}";
        }
    }    
    
  • POST MAN 接口测试
    在这里插入图片描述
集合类型参数
  • 请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        //设置当前操作的访问路径
        @RequestMapping("/save")
        //设置当前操作的返回类型
        @ResponseBody
        public String save(@RequestParam List<String> hobbies){
            System.out.println("集合参数传递" + hobbies);
            return "{'module':'springmvc'}";
        }
    }    
    
  • POST MAN 接口测试
    在这里插入图片描述
响应json数据(开发常见的方式)
  • 在pom.xml文件中导入处理json格式的依赖坐标

    <dependency>
         <groupId>com.fasterxml.jackson.core</groupId>
         <artifactId>jackson-databind</artifactId>
         <version>2.9.5</version>
    </dependency>
    
  • 在核心配置中添加注解@EnableWebMvc,开启自动转换json数据的支持

    //创建springmvc的配置文件,加载controller对应的bean
    @Configuration
    @ComponentScan("com.itheima.controller")
    @EnableWebMvc
    public class SpringMvcConfig {
    }
    
  • 在POST MAN接口测试中选择如下选项(确定传递的数据为JSON格式)
    在这里插入图片描述

  • 在Controller对应的函数的形参中添加@ReuestBody注解

  • 传递json数组:

    @Controller
    @RequestMapping("/user")
    public class UserController {
    
       //设置当前操作的访问路径
       @RequestMapping("/save")
       //设置当前操作的返回类型
       @ResponseBody
       public String save(@RequestBody List<String> hobbies){
           System.out.println("json格式数组参数传递" + hobbies);
           return "{'module':'springmvc'}";
       }
    }   
    
  • 传递json对象

    /**
     *  {
     *   "name":"xukun cai",
     *    "age":22
     *  }
     */
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        //设置当前操作的访问路径
        @RequestMapping("/save")
        //设置当前操作的返回类型
        @ResponseBody
        public String save(@RequestBody User user){
            System.out.println("json对象格式参数传递" + user);
            return "{'module':'springmvc'}";
        }
    }	    
    
  • 传递json对象数组

    /**
     * [
     *     {
     *         "name":"xukun cai",
     *         "age":22
     *     },
     *     {
     *         "name":"fengjie",
     *         "age":50
     *     }
     * ]
     */
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        //设置当前操作的访问路径
        @RequestMapping("/save")
        //设置当前操作的返回类型
        @ResponseBody
        public String save(@RequestBody User[] user){
            System.out.println("json格式对象数组参数传递" + Arrays.toString(user));
            return "{'module':'springmvc'}";
        }
    }   
    
日期类型参数传递
  • 日期类型数据基于系统不同格式也不近相同,如:
    • 2000-12-31
    • 2000/12/31
    • 12/31/2000
  • 接收型参时,根据不同的日期格式设置不同的接收方式,使用@DateTimeFormate注解
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        @RequestMapping("/update")
        @ResponseBody
        public String update(Date date1,
                             @DateTimeFormat(pattern = "yyyy-MM-dd") Date date2,
                             @DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss") Date date3){
            System.out.println("参数传递 date1 ==>" + date1);
            System.out.println("参数传递 date2(yyyy-MM-dd) ==>" + date2);
            System.out.println("参数传递 date3(yyyy/MM/dd HH:mm:ss) ==>" + date3);
    
            return "{'module':'update'}";
        }
    }
    

响应

响应JSON数据(对象转JSON)
  • 【注意】:一定要导入jackson-core这个依赖坐标,否则是无法实现对象转JSON格式

  • 响应JSON数据(对象转JSON)

    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        @RequestMapping("/add")
        @ResponseBody
        public User add(){
            User user = new User();
            user.setName("赵云");
            user.setAge(30);
            return user;
        }
    } 
    
  • 响应JSON数据(对象转JSON数组)

    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        @RequestMapping("/insert")
        @ResponseBody
        public List<User> insert(){
            User user1 = new User();
            User user2 = new User();
    
            user1.setName("马云");
            user1.setAge(58);
    
            user2.setName("马化腾");
            user2.setAge(51);
    
            List<User> user = new ArrayList<User>();
            user.add(user1);
            user.add(user2);
    
            return user;
        }
    }
    
  • 实验结果分析:通常需要在Controller类对应的函数中添加@ResponseBody注解,其作用是设置当前控制器返回值作为响应体 在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值