SpringMVC的学习

SpringMVC

学习目标

  1. 掌握基于SpringMVC获取请求参数与响应json数据操作
  2. 熟练应用基于REST风格的请求路径设置与参数传递
  3. 能够根据实际业务建立前后端开发通信协议并进行实现
  4. 基于SSM整合技术开发任意业务模块功能

SpringMVC简介

  • SpringMVC技术与Servlet技术功能等同,均属于web层开发技术
  • SpringMVC是一种基于Java实现MVC模型的轻量级web(表现层)框架
  • SpringMVC是一种表现层框架技术,用于进行表现层功能开发

在这里插入图片描述

优点

  • 使用简单,开发便捷(相比于Servlet)
  • 灵活性强

入门案例

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

    <dependencies>
        <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>
      </dependencies>
    
  2. 创建SpringMVC控制器类(等同于Servlet功能)

    //定义表现层控制器bean
    @Controller
    public class UserController {
    
        //设置映射路径为/save,即外部访问路径
        @RequestMapping("/save")
        //设置当前操作返回结果为指定json数据(本质上是一个字符串信息)
        @ResponseBody
        public String save(){
            System.out.println("user save ...");
            return "{'info':'springmvc'}";
        }
    
        //设置映射路径为/delete,即外部访问路径
        @RequestMapping("/delete")
        @ResponseBody
        public String delete(){
            System.out.println("user save ...");
            return "{'info':'springmvc'}";
        }
    }
    
    
  3. 初始化SpringMVC环境(同Spring环境),设定SpringMVC加载对应的bean

    //springmvc配置类,本质上还是一个spring配置类
    @Configuration
    @ComponentScan("com.itheima.controller")
    public class SpringMvcConfig {
    }
    
    
  4. 加载SpringMVC环境,并设置SpringMVC技术处理的请求,专用于加载springmvc的核心配置,我们需要做的就是创建空容器并注册,返回出去

    //4.定义一个servlet容器的启动配置类,在里面加载springmvc的配置
    public class ServletContainitConfig extends AbstractDispatcherServletInitializer {
        //加载Springmvc容器配置的
        @Override
        protected WebApplicationContext createServletApplicationContext() {
            AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
            //上方操作完成后并未加载MVC的配置,所以是一个空的容器,需要以下操作来加载配置
            ctx.register(SpringMvcConfig.class);
            return ctx;
        }
    
        //设置哪些请求归springmvc处理的
        @Override
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
    
        //加载spring容器配置,注意与springMVC区分
        @Override
       AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
            //上方操作完成后并未加载MVC的配置,所以是一个空的容器,需要以下操作来加载配置
            ctx.register(SpringConfig.class);
            return ctx;
    }
    
    
    

    5.导入tomcat坐标

     <build>
        <plugins>
          <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.1</version>
            <configuration>
              <port>80</port>
              <path>/</path>
            </configuration>
          </plugin>
        </plugins>
      </build>
    

springmvc入门程序开发流程

  • 一次性工作
    • 创建工程,设置服务器,加载工程
    • 导入坐标
    • 创建web容器启动类,加载springMVC配置,并设置SpringMVC请求拦截路径
    • springmvc核心配置类,(设置配置类,扫描controller包,加载Controller控制器bean)
  • 多次工作
    • 定义处理请求的控制器类
    • 定义处理请求的控制器方法,并设置映射路径@RequestMapping(“”),与返回json数据@ResponseBody

入门案例工作流程分析

  • 启动服务器初始化过程

    1. 服务器启动,执行ServletContaInitConfig类,初始化web容器
    2. 执行createServletApplicationContext()方法,创建WebApplicationContext对象
    3. 加载SpringMvcConfig
    4. 执行@Controller加载对应的bean
    5. 加载UserController,每个@RequestMapping(“”)对应一个具体的方法
    6. 执行 getServletMappings()方法,定义所有的请求都通过SpringMVC

    在这里插入图片描述

  • 单次请求过程

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

SpringMVC对应bean加载与spring对应bean加载

  • SpringMVC相关bean(表现层bean)
  • Spring控制的bean
    • 业务bean(Service)
    • 功能bean(DataSource等)

产生问题:因为功能不同如何避免Spring错误加载到SpringMVC的bean?

  • 方案

    • 加载Spring控制的bean的时候,排除掉SpringMVC控制的bean
  • SpringMVC相关的bean控制

    • springMVC加载的包对应的包均在com.ityc.controller包内
  • Spring相关bean加载控制

    • 方式一:Spring加载的bean设定扫描范围为com.ityc,排除掉controller包内的bean
    • 方式二:Spring加载的bean设定骚尼奥范围为精准范围,例如:service包,dao包等
    • 方式三:不区分spring与soringMVC的环境,加载在同一环境中
//创建Spring的配置文件,
@Configuration
//方案1
//@ComponentScan({"com.ityc.service","com.ityc.dao"})

//方案二
//设置spring配置类加载bean时的过滤规则,当前要求排除掉表现层对应的bean
//excludeFilters属性:设置扫描加载bean时,排除的过滤规则
//type属性:设置排除规则,当前使用按照bean定义时的注解类型进行排除
//classes属性:设置排除的具体注解类,当前设置排除@Controller定义的bean
@ComponentScan(value = "com.ityc",
        excludeFilters =@ComponentScan.Filter(
                type = FilterType.ANNOTATION,//使用此方式,将排除我们指定的注解对应的包,spring就不会加载本包对应的bean
                classes = Controller.class
        )
)
public class SpringConfig {

}

在这里插入图片描述


web配置类简化开发

配置环境

extends AbstractAnnotationConfigDispatcherServletInitializer

//web配置类简化开发,仅设置配置类类名即可
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {

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

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

    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}
/*
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringConfig.class);
        return ctx;
    }
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

}
*/

PostMan插件

简介

  • PostMan是一款功能强大的网页调试与发送网页http请求的Chrome插件
  • 作用:常用于接口测试
  • 特征:
    • 简单
    • 实用
    • 美观
    • 大方

基本使用

  • 注册登录
  • 创建工作空间/进入工作空间
  • 发起请求测试结果

请求与响应

请求映射路径

思考:

1.团队多人开发,没人设置不同的请求路径,冲突问题如何解决?~设置模块名作为请求路径前缀

@Controller
//请求路径的前缀
//代表该模块所有的请求路径前都加book
@RequestMapping("/book")
public class BookController {
    @RequestMapping("save")
    @ResponseBody
    public String save(){
        System.out.println("book save...");
        return "{'module':'book save'}";
    }


    @RequestMapping("delete")
    @ResponseBody
    public String delete(){
        System.out.println("book delete...");
        return "{'module':'book delete'}";
    }
}

请求参数

(传参)

请求方式
  • Get请求

    • http://localhost/commonParam?name=yc&age=18
  • Post请求

    • postMan发送携带参数Post请求

    • springMvc解决Post请求中文乱码问题

      public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
          protected Class<?>[] getRootConfigClasses() {
              return new Class[0];
          }
      
          protected Class<?>[] getServletConfigClasses() {
              return new Class[]{SpringMvcConfig.class};
          }
      
          protected String[] getServletMappings() {
              return new String[]{"/"};
          }
      
          //乱码处理,设置过滤器
          @Override
          protected Filter[] getServletFilters() {
              CharacterEncodingFilter filter = new CharacterEncodingFilter();
              filter.setEncoding("UTF-8");
              return new Filter[]{filter};
             // return new Filter[]{filter,filter2,filter3};
          }
      }
      
      
  • 参数种类

    • 普通参数
    • POJO类型参数
    • 嵌套POJO类型参数
    • 数组类型参数
    • 集合类型参数
  • 不同类型的参数的传递

    @Controller
    public class UserController {
    
        //普通参数:请求参数与形参名称对应即可完成参数传递
        @RequestMapping("/commonParam")
        @ResponseBody
        public String commonParam(String name ,int age){
            System.out.println("普通参数传递 name ==> "+name);
            System.out.println("普通参数传递 age ==> "+age);
            return "{'module':'common param'}";
        }
    
        //普通参数:请求参数与形参名不同解决完成参数传递利用@RequestParam注解
        @RequestMapping("/commonParamDifferentName")
        @ResponseBody
        public String commonParamDifferentName(@RequestParam("name") String username ,int age){
            //@RequestParam("name")利用该注解,绑定name到username,也就是绑定请求参数与形参之间的关系
            System.out.println("普通参数传递 name ==> "+username);
            System.out.println("普通参数传递 age ==> "+age);
            return "{'module':'commonDifferentName param'}";
        }
    
        //pojo参数,实体类
        @RequestMapping("/pojoParam")
        @ResponseBody
        public String pojoParam(User user){
            System.out.println("pojo参数传递 user ==> "+user);
            return "{'module':'pojo param'}";
        }
    
        //pojo嵌套参数
        @RequestMapping("/pojoContainParam")
        @ResponseBody
        public String pojoContainParam(User user){
            System.out.println("pojo参数传递 user ==> "+user);
            return "{'module':'pojo  param'}";
        }
    
        //数组参数
        @RequestMapping("arrayParam")
        @ResponseBody
        public String arrayParam(String[] likes){
            System.out.println("数组参数传递 user ==> "+Arrays.toString(likes));
            return "{'module':'array  param'}";
        }
    
        //集合参数
        @RequestMapping("listParam")
        @ResponseBody
        public String listParam(@RequestParam List<String> likes){
            System.out.println("集合参数传递 user ==> "+likes);
            return "{'module':'list  param'}";
        }
    }
    
  • 请求参数与形参名不同解决完成参数传递利用@RequestParam注解

请求参数(传递json数据)

步骤:
//1.pom.xml导入json坐标
    
//2.在springmvc配置中中开启开启json数据类型自动转换
@EnableWebMvc
//3.@RequestBody   注解
  • json数组
  • json对象(pojo)
  • json数组(pojo)
 //数组参数:(JSON)格式
    @RequestMapping("/listParamForJson")
    @ResponseBody
    public String listParamForJson(@RequestBody List<String> likes){
        System.out.println("集合参数传递 user ==> "+likes);
        return "{'module':'list  param'}";
    }

    //集合参数:(JSON)格式
    @RequestMapping("/pojolistParamForJson")
    @ResponseBody
    public String pojoParamForJson(@RequestBody User user){
        System.out.println("集合参数传递 user ==> "+user);
        return "{'module':'pojolist param'}";
    }

    //pojo参数:(JSON)格式
    @RequestMapping("/listPojoParamForJson")
    @ResponseBody
    public String listPojoParamForJson(@RequestBody List<User> list){
        System.out.println("集合参数传递 user ==> "+ list);
        return "{'module':'Pojo  param'}";
    }


@RequestBody与@RequestParam区别

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

小结:

1.json数据传递与接收

2.@EnableWebMvc注解

3.@RequestBody

日期类型参数传递

  • 日期类型数据基于系统不同格式也不尽相同
    • 2011-01-11
    • 2011/01/11
    • 01/11/2011
 //日期型参数
    @RequestMapping("/dataParam")
    @ResponseBody
    public String dataParam(Date date,
                            @DateTimeFormat(pattern = "yyyy-MM-dd") Date date1,
                            @DateTimeFormat(pattern = "yyyy/MM/dd HH:MM:SS") Date date2

    ){
        System.out.println("参数传递 date==> "+ date);
        System.out.println("参数传递yyyy-MM-dd date1 ==> "+ date1);
        System.out.println("参数传递yyyy/MM/dd HH:MM:SS date2==> "+ date2);
        return "{'module':'date  param'}";
    }

响应

  • 响应页面
  • 响应数据
    • 文本数据
    • json数据
@Controller
public class UserController {

    //响应页面/跳转页面
    //返回值为String类型,设置返回值为页面名称,即可实现页面跳转
    @RequestMapping("/toJumpPage")
    public String toJumpPage(){
        System.out.println("跳转页面");
        return "page.jsp";
    }

    //响应文本数据
    //返回值为String类型,设置返回值为任意字符串信息,即可实现返回指定字符串信息,需要依赖@ResponseBody注解
    @RequestMapping("/toText")
    @ResponseBody
    public String toText(){
        System.out.println("返回纯文本数据");
        return "response text";
    }

    //响应POJO对象
    //返回值为实体类对象,设置返回值为实体类类型,即可实现返回对应对象的json数据,需要依赖@ResponseBody注解和@EnableWebMvc注解
    @RequestMapping("/toJsonPOJO")
    @ResponseBody
    public User toJsonPOJO(){
        System.out.println("返回json对象数据");
        User user = new User();
        user.setName("itcast");
        user.setAge(15);
        return user;
    }

    //响应POJO集合对象
    //返回值为集合对象,设置返回值为集合类型,即可实现返回对应集合的json数组数据,需要依赖@ResponseBody注解和@EnableWebMvc注解
    @RequestMapping("/toJsonList")
    @ResponseBody
    public List<User> toJsonList(){
        System.out.println("返回json集合数据");
        User user1 = new User();
        user1.setName("ityc");
        user1.setAge(15);

        User user2 = new User();
        user2.setName("itheima");
        user2.setAge(12);

        List<User> userList = new ArrayList<User>();
        userList.add(user1);
        userList.add(user2);

        return userList;
    }
}

注解:@ResponseBody

  • 位置:SpringMvc控制器方法定义上方
  • 作用:
    • 设置当前控制器,方法响应内容为当前返回值,无需解析
    • 设置当前控制器返回值为响应体

类型转换器

  • HttpMessageConverter接口

REST风格

  • REST简介

    • 表现形式状态转换
  • 传统风格资源描述形式

    http://localhost/user/getId?id=1
    http://localhost/user/saveUser
    
  • REST风格描述形式

    http://localhost/user/1
    http://localhost/user
    
  • 优点:

    • 隐藏资源的访问行为,无法通过地址得知对资源是何种操作
    • 书写简化
  • 按照REST风格访问资源时使用行为动作区分对资源进行了何种操作

    http://localhost/users     查询全部用户信息     GET(查询)
    http://localhost/users/1   查询指定用户信息     GET(查询)
    http://localhost/users     添加用户信息		POST(新增/保存)
    http://localhost/users     修改用户信息		PUT(修改/更新)
    http://localhost/users/1   删除用户信息		DELETE(删除)
    

    注意:

    上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范,

    描述模块的名称通常使用复数,也就是加S的格式描述,而非单个资源,例如:users,books,accounts…

  • 根据REST风格对资源进行访问称为RESTful

RESTful入门案例

步骤:

1.设定http请求动作:post,get,put等等

2.设置请求参数(路径变量)

  • 路径中要有我们的参数占位
  • 在方法形参中与占位变量对应上,并且加上@PathVariable注解
//请求方法设定


@Controller
//请求路径的前缀
public class BookController {
    @RequestMapping(value = "/users",method = RequestMethod.POST)
    @ResponseBody
    public String save(){
        System.out.println("book save...");
        return "{'module':'user save'}";
    }


    @RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable Integer id){
        System.out.println("book delete..."+id);
        return "{'module':'book delete'}";
    }
    @RequestMapping(value = "/users",method = RequestMethod.PUT)
    @ResponseBody
    public String update(@RequestBody User user){
        System.out.println("book PUT..."+user);
        return "{'module':'book PUT'}";
    }


    @RequestMapping(value = "/users/{id}",method = RequestMethod.GET)
    @ResponseBody
    public String getById(@PathVariable Integer id){
        System.out.println("book id..."+id);
        return "{'module':'book id'}";
    }


    @RequestMapping(value = "/users",method = RequestMethod.GET)
    @ResponseBody
    public String getAll(){
        System.out.println("book getALL...");
        return "{'module':'book GETALL'}";
    }

}
  • 区分@RequestBody @RequestParam @PathVariable
  • 区别:
    • @RequestParam:用于接收url地址传参或表单传参
    • @RequestBody:用于接收json数据
    • @PathVariable:用于接收路径参数,使用{参数名称}描述路径参数
  • 应用:
    • 后期开发中,发送请求参数超过一个时,以json格式为主,@RequestBody应用较广
    • 如果发送非json格式数据,则采用@RequestParam接收请求参数
    • 采用RESTful进行开发,当参数数量较少是,例如一个,则可以采用@PathVariable接收请求路径变量,通常用于传递id值。
REST快速开发
  • @RestController注解

    • 设置当前控制器类为RESTful风格,等同于@Controller与@ResponseBody两个注解的组合
  • @PostMapping,@PutMapping,@GetMapping,@DeleteMapping

    • 设置当前控制器方法请求访问路径与请求动作,每种对应一种请求动作,例如@PostMapping对应post请求
    //@Controller
    //请求路径的前缀
    //@ResponseBody
    @RestController
    @RequestMapping("users")
    public class BookController {
        //@RequestMapping(method = RequestMethod.POST)
        @PostMapping
        public String save(){
            System.out.println("book save...");
            return "{'module':'user save'}";
        }
    
        //@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
        @DeleteMapping("{id}")
        public String delete(@PathVariable Integer id){
            System.out.println("book delete..."+id);
            return "{'module':'book delete'}";
        }
        //@RequestMapping(method = RequestMethod.PUT)
        @PutMapping
        public String update(@RequestBody User user){
            System.out.println("book PUT..."+user);
            return "{'module':'book PUT'}";
        }
    
        //@RequestMapping(value = "/{id}",method = RequestMethod.GET)
        @GetMapping("{id}")
        public String getById(@PathVariable Integer id){
            System.out.println("book id..."+id);
            return "{'module':'book id'}";
        }
    
        //@RequestMapping(method = RequestMethod.GET)
        @GetMapping
        public String getAll(){
            System.out.println("book getALL...");
            return "{'module':'book GETALL'}";
        }
    }
    
案例:基于RESTful页面数据交互
  1. 制作SpringMVC控制器,并通过PostMan测试接口功能。

  2. 设置对静态资源的访问放行

  3. 前端页面通过异步提交访问后台控制器

    //注意:要在SpringMVC中添加本配置
    @Configuration
    public class SpringMvcSupport extends WebMvcConfigurationSupport {
        @Override
        protected void addResourceHandlers(ResourceHandlerRegistry registry) {
            //当访问/pages/????时不要走mvc,走/pages目录下的内容
            registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
            registry.addResourceHandler("/js/**").addResourceLocations("/js/");
            registry.addResourceHandler("/css/**").addResourceLocations("/css/");
            registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
    
        }
    }
    
    
    //添加
    saveBook () {
        axios.post("http://localhost/books.",this.formData).then((res)=>{
    
        });
    },
    
    //主页列表查询
    getAll() {
        axios.get("http://localhost/books.").then((res)=>{
           this.dataList = res.data;
        });
    },
    
//案例
@RestController
@RequestMapping("/books")
public class BookController {

    @PostMapping
    public String save(@RequestBody Book book){
        System.out.println("book save ====>"+book);
        return "{'module':'book save success'}";
    }


    @GetMapping
    public List<Book> getAll(){
        System.out.println("book  getAll is running...");

        ArrayList<Book> bookList = new ArrayList<Book>();

        Book book1 = new Book();
        book1.setType("计算机");
        book1.setName("SpringMVC入门教程");
        book1.setDescription("试试就是是");
        bookList.add(book1);

        Book book2 = new Book();
        book2.setType("计算机2");
        book2.setName("Spring入门教程");
        book2.setDescription("试是实施");
        bookList.add(book2);

        Book book3 = new Book();
        book3.setType("计算机3");
        book3.setName("Spring进阶");
        book3.setDescription("实事求是");
        bookList.add(book3);

        return bookList;
    }

}

小结:

  1. 先做好后台功能,开发接口并调通接口
  2. 再做页面异步调用,确认功能可以正常访问
  3. 最后完成页面数据展示
  4. 补充:放行静态资源访问
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玥骋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值