三、Java框架之SpringMVC1_MVC基础

news2024/10/5 18:32:06

文章目录

  • 1. SpringMVC简介
    • 1.1 回顾Servlet技术
    • 1.2 SpringMVC入门案例
      • 步骤1:创建javaweb项目,并导入jar包
      • 步骤2:创建Controller
      • 步骤3:创建SpringMVC的配置文件
      • 步骤4:使用配置类替换web.xml
      • 步骤5:启动项目并访问
      • 注解:@Controller @RequestMapping @ResponseBody
      • **注意事项**
    • 1.3 SpringMVC工作流程
      • 启动服务器初始化过程
      • 单次请求过程
    • 1.4 bean的加载控制
  • 2. PostMan测试工具
  • 3. 请求
    • 3.1 设置请求映射路径
    • 3.2 设置请求参数
      • 普通参数
      • 中文乱码处理(post)
      • 参数名称不一致的问题
      • pojo实体类参数
      • pojo实体类参数(嵌套)
      • array数组参数
      • list集合参数
    • 3.3 传递json数据(更常用)
      • 准备工作
      • JSON普通数组
      • JSON传递对象
      • JSON对象数组
      • @RequestBody与@RequestParam区别
    • 3.4 日期类型参数传递
    • 3.5 内部实现原理
  • 4. 响应
    • 4.1 响应不同类型的数据
    • 4.2 @ResponseBody
  • 5. REST风格
    • 5.1 Rest简介
    • 5.2 RESTful入门案例
    • 5.3 接收参数的三种方法
    • 5.4 RESTful快速开发
    • 5.5 RESTful案例
      • 步骤1:pom.xml
      • 步骤2:Controller类
      • 步骤3:postman测试
      • 步骤4:前端资源的放行

1. SpringMVC简介

1.1 回顾Servlet技术

package servlet;

@WebServlet("/user/save")
public class UserSaveServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 接收请求参数
        String name = req.getParameter("name");
        //2. 产生响应
        resp.setContentType("text/json;charset=utf-8");
        PrintWriter pw = resp.getWriter();
        pw.write("UserSaveServlet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

启动:mvn tomcat7:run

servlet问题之一:如果要接收多个参数,要么将它们抽取成一个实体类,要么多行getParameter
SpringMVC可以实现Servlet一样的功能,但更加简便

1.2 SpringMVC入门案例

需要javaweb前置知识

MVC是指表现层,业务层(service),数据层(dao)
之前的表现层是用servlet实现,现在学习通过SpringMVC来实现表现层

  • SpringMVC是一种基于Java实现MVC模型的轻量级Web框架
  • 优点
    • 使用简单,开发便捷(相比于Servlet)
    • 灵活性强

步骤1:创建javaweb项目,并导入jar包

<dependencies>
    <!-- 导入坐标springmvc和servlet -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- webmvc-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <!-- tomcat插件 -->
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
        </plugin>
    </plugins>
</build>

注意,这里可以设置项目启动的端口和路径

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

这样设置后对应的访问路径就如:http://localhost/save

步骤2:创建Controller

package org.example.controller;

//2. 定义Controller
//2.1 使用@Controller定义bean
@Controller
public class UserController {
    //2.2 设置当前操作的访问路径
    @RequestMapping("/save")
    //2.3 设置当前操作的返回值类型
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'module':'springmvc'}";
    }
}

步骤3:创建SpringMVC的配置文件

package org.example.config;

//3. 创建SpringMVC的配置文件
@Configuration
@ComponentScan("org.example.controller")
public class SpringMvcConfig {
}

步骤4:使用配置类替换web.xml

将web.xml删除,换成ServletContainersInitConfig

package org.example.config;

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

重点:

  • 创建web容器启动类,加载SpringMVC配置,并设置SpringMVC请求拦截路径
  • SpringMVC核心配置类(设置配置类,扫描controller包,加载Controller控制器bean)

步骤5:启动项目并访问

启动:mvn tomcat7:run
访问:http://localhost:8080/springmvc/save

在这里插入图片描述

注解:@Controller @RequestMapping @ResponseBody

名称@Controller
类型类注解
位置SpringMVC控制器类定义上方
作用设定SpringMVC的核心控制器bean
名称@RequestMapping
类型类注解或方法注解
位置SpringMVC控制器类或方法定义上方
作用设置当前控制器方法请求访问路径
相关属性value(默认),请求访问路径
名称@ResponseBody
类型类注解或方法注解
位置SpringMVC控制器类或方法定义上方
作用设置当前控制器方法响应内容为当前返回值,无需解析

注意事项

  • SpringMVC是基于Spring的,在pom.xml只导入了spring-webmvcjar包的原因是它会自动依赖spring相关坐标
  • AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类
  • AbstractDispatcherServletInitializer提供了三个接口方法供用户实现
    • createServletApplicationContext方法,创建Servlet容器时,加载SpringMVC对应的bean并放入WebApplicationContext对象范围中,而WebApplicationContext的作用范围为ServletContext范围,即整个web容器范围
    • getServletMappings方法,设定SpringMVC对应的请求映射路径,即SpringMVC拦截哪些请求
    • createRootApplicationContext方法,如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,使用方式和createServletApplicationContext相同。
  • createServletApplicationContext用来加载SpringMVC环境
    createRootApplicationContext用来加载Spring环境

1.3 SpringMVC工作流程

启动服务器初始化过程

在这里插入图片描述

  1. 服务器启动,执行ServletContainersInitConfig类,初始化web容器

    • 功能类似于以前的web.xml
  2. 执行createServletApplicationContext方法,创建了WebApplicationContext对象

    • 该方法加载SpringMVC的配置类SpringMvcConfig来初始化SpringMVC的容器
    • 这个WebApplicationContext容器被放在ServletContext容器中,后者是Servlet中最大的一个接口
  3. 加载SpringMvcConfig配置类

  4. 执行@ComponentScan加载对应的bean

    • 扫描指定包及其子包下所有类上的注解,如Controller类上的@Controller注解
  5. 加载UserController,每个@RequestMapping的名称对应一个具体的方法

    • 此时就建立了 /save 和 save方法的对应关系
    • 所有的映射关系是放在一起统一管理的,而非在各自的bean里面
  6. 执行getServletMappings方法,设定SpringMVC拦截请求的路径规则

    protected String[] getServletMappings() {
        return new String[]{"/"}; //所有请求都归SpringMVC处理
    }
    

    /代表所拦截请求的路径规则,只有被拦截后才能交给SpringMVC来处理请求

单次请求过程

  1. 发送请求http://localhost:8080/springmvc/save
  2. web容器发现该请求满足SpringMVC拦截规则,将请求交给SpringMVC处理
  3. 解析请求路径/save
  4. 根据@RequestMapping定义的映射关系,由/save匹配执行对应的方法save()
  5. 执行save()
  6. 检测到有@ResponseBody直接将save()方法的返回值作为响应体返回给请求方

1.4 bean的加载控制

概述

contrller、service和dao这些类都需要被容器管理成bean对象,那么到底是该让SpringMVC加载还是让Spring加载呢?

  • SpringMVC加载其相关bean(表现层bean),也就是controller包下的类
  • Spring控制的bean
    • 业务bean (Service)
    • 功能bean (DataSource,SqlSessionFactoryBean,MapperScannerConfigurer等)

排除bean的方法

为了避免Spring加载到SpringMVC的bean,需要在加载Spring控制的bean时,排除掉SpringMVC控制的bean

  • SpringMVC相关bean的加载控制

    • SpringMVC加载的bean对应的包均在org.example.controller中
  • Spring相关bean的加载控制

    • 方式一:Spring加载的bean设定扫描范围为精准范围,例如service包、dao包等

      package org.example.config;
      
      @Configuration
      @ComponentScan({"org.example.service", "org.example.dao"})
      public class SpringConfig {
      }
      

      使用mybatis自动代理时,这里的dao包是否可以不扫描?

    • 方式二:Spring加载的bean设定扫描范围为org.example,排除掉controller包中的bean

      package org.example.config;
      
      @Configuration
      @ComponentScan(value = "org.example",
              excludeFilters = @ComponentScan.Filter(
                      type = FilterType.ANNOTATION, //设置按照注解过滤
                      classes = Controller.class  //过滤的注解类型是Controller
              ))
      public class SpringConfig {
      }
      

      excludeFilters:排除扫描路径中加载的bean
      includeFilters:加载指定的bean

    • 方式三:不区分Spring与SpringMVC的环境,加载到同一个环境中

测试

先将SpringMvcConfig里面的@ComponentScan注释掉,避免SpringMVC加载Controller的bean
此时就只剩下Spring会加载bean

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);//也可以通过register的方式
    System.out.println(ctx.getBean(UserController.class));
}

结果发现getBean无法获取到UserController对象,说明该bean没有被加载

2. PostMan测试工具

PostMan是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件,常用于进行接口测试

  • 下载安装
    https://www.postman.com/downloads/
    双击下载好的应用,无需安装,根据提示注册账号即可进入postman

  • 创建一个新的workspace

    在这里插入图片描述

  • 发送请求

    在这里插入图片描述

  • 保存请求地址

    如果希望保存请求地址,方便下次测试,只需要点击save,并将其加入到一个集合中即可
    在这里插入图片描述
    此时可以看到保存好的请求出现在左侧
    在这里插入图片描述

3. 请求

3.1 设置请求映射路径

为了避免重名,每一个模块应该添加一个请求路径前缀

package org.example.controller;

@Controller
@RequestMapping("/book")//设置请求路径的前缀
public class BookController {
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("book save ...");
        return "{'module':'book save'}";
    }
}

3.2 设置请求参数

普通参数

package org.example.controller;

@Controller
@RequestMapping("/user")
public class UserController {
    //普通参数
    @RequestMapping("/commonParam")
    @ResponseBody
    public String commonParam(String name, int age){
        System.out.println("普通参数传递:name="+name+",age="+age);
        return "{'module':'common param'}";
    }
}
  • get方式
    在这里插入图片描述

  • post方式

    body里面选择x-www-form-urlencoded
    在这里插入图片描述

中文乱码处理(post)

在ServletContainersInitConfig配置类中重写getServletFilters

//乱码处理
@Override
protected Filter[] getServletFilters() {
    CharacterEncodingFilter filter = new CharacterEncodingFilter();
    filter.setEncoding("UTF-8");
    return new Filter[]{filter};
}

注意这样做只能处理post请求的中文乱码,get需要先编码再解码(之后补充)

参数名称不一致的问题

当请求里面的参数名称和后台函数中的参数名称不一致时,可以通过@RequestParam("name")注解来解决

public String commonParam(@RequestParam("name") String userName, @RequestParam("age") int age){
    System.out.println("普通参数传递:userName="+userName+",age="+age);
    return "{'module':'common param'}";
}

pojo实体类参数

package org.example.controller;

@Controller
@RequestMapping("/user")
public class UserController {
   //POJO参数
   @RequestMapping("/pojoParam")
   @ResponseBody
   public String pojoParam(User user){
       System.out.println("pojo参数传递:user="+user);
       return "{'module':'pojo param'}";
   }
}

在postman中,无论是get方式还是post方式,发送实体类参数方法是和发送普通参数一样的,它将自动和User类里面的属性匹配

pojo实体类参数(嵌套)

当User类里面多了一个对象Address,此时发送时需要
在这里插入图片描述

post方法同理

array数组参数

package org.example.controller;

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/arrayParam")
    @ResponseBody
    public String arrayParam(String[] likes){
        System.out.println("数组参数传递:likes="+ Arrays.toString(likes));
        return "{'module':'array param'}";
    }
}

在这里插入图片描述

post方法同理

list集合参数

package org.example.controller;

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/listParam")
    @ResponseBody
    public String listParam(@RequestParam List<String> likes) {
        System.out.println("集合参数传递:likes=" + likes);
        return "{'module':'list param'}";
    }
} 

此时再按照array的方法发出请求即可。如果不加RequestParam,likes将被当成一个对象初始化,然而List是接口不是对象,因此报错

3.3 传递json数据(更常用)

准备工作

步骤1:导入json坐标

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

步骤2:开启SpringMVC注解支持

SpringMVC的配置类中开启SpringMVC的注解支持,这里面就包含了将JSON转换成对象的功能

package org.example.config;

@Configuration
@ComponentScan("org.example.controller")
@EnableWebMvc
public class SpringMvcConfig {
}

JSON普通数组

package org.example.controller;

@Controller
@RequestMapping("/user")
public class UserController {
    //普通集合参数:json格式
    @RequestMapping("/listParamForJson")
    @ResponseBody
    public String listParamForJson(@RequestBody List<String> likes){
        System.out.println("list common(json)参数传递:list="+likes);
        return "{'module':'list common for json param'}";
    }
}

在这里插入图片描述

JSON传递对象

package org.example.controller;

@Controller
@RequestMapping("/user")
public class UserController {
    //POJO参数:json格式
    @RequestMapping("/pojoParamForJson")
    @ResponseBody
    public String pojoParamForJson(@RequestBody User user){
        System.out.println("pojo(json)参数传递:user="+user);
        return "{'module':'pojo for json param'}";
    }
}

在这里插入图片描述

JSON对象数组

package org.example.controller;

@Controller
@RequestMapping("/user")
public class UserController {
    //对象集合参数
    @RequestMapping("/listPojoParamForJson")
    @ResponseBody
    public String listPojoParamForJson(@RequestBody List<User> users){
        System.out.println("list pojo(json)参数传递:users="+users);
        return "{'module':'list pojo for json param'}";
    }
}

在这里插入图片描述

@RequestBody与@RequestParam区别

  • 区别

    • @RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded】
    • @RequestBody用于接收json数据【application/json】
  • 应用

    • 后期开发中,发送json格式数据为主,@RequestBody应用较广
    • 如果发送非json格式数据,选用@RequestParam接收请求参数

3.4 日期类型参数传递

  • 默认情况下

    //日期参数
    @RequestMapping("/dateParam")
    @ResponseBody
    public String dateParam(Date date){
        System.out.println("日期参数传递:date="+date);
        return "{'module':'date param'}";
    }
    

    发送请求

    http://localhost:8080/springmvc/user/dateParam?date=2022/08/06
    

    获取到的date为

    Sat Aug 06 00:00:00 CST 2022
    
  • 设置日期格式:@DateTimeFormat

    //日期参数
    @RequestMapping("/dateParam")
    @ResponseBody
    public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date){
        System.out.println("日期参数传递:date="+date);
        return "{'module':'date param'}";
    }
    

    发送请求

    http://localhost:8080/springmvc/user/dateParam?date=2022-08-06
    

    获取到的date为

    Sat Aug 06 00:00:00 CST 2022
    
  • 添加时间属性

    //日期参数
    @RequestMapping("/dateParam")
    @ResponseBody
    public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date date){
        System.out.println("日期参数传递:date="+date);
        return "{'module':'date param'}";
    }
    

    发送请求

    http://localhost:8080/springmvc/user/dateParam?date=2022-08-06 8:08:08
    

    获取到的date为

    Sat Aug 06 08:08:08 CST 2022
    

3.5 内部实现原理

考虑以下情况:

  • 前端传递字符串,后端使用日期Date接收
  • 前端传递JSON数据,后端使用对象接收
  • 前端传递字符串,后端使用Integer接收

后台需要的数据类型有很多种,在数据的传递过程中存在很多类型的转换,那么谁来做这个类型转换?

  • SpringMVC

SpringMVC中提供了很多类型转换接口和实现类,例如Convert接口

  • Convert接口

    package org.springframework.core.convert.converter;
    
    @FunctionalInterface
    public interface Converter<S, T> {
        @Nullable
        T convert(S var1);
    }
    

    用来实现不同数据类型之间的转换,如:

    • 请求参数年龄数据(String→Integer)

    • 日期格式转换(String → Date)

  • @EnableWebMvc:功能之一就是根据类型匹配对应的类型转换器

4. 响应

4.1 响应不同类型的数据

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.0</version>
</dependency>
package org.example.controller;

@Controller
@RequestMapping("/user")
public class UserController {
    //响应页面/跳转页面
    @RequestMapping("/toJumpPage")
    public String toJumpPage(){
        System.out.println("跳转界面");
        return "/page.jsp";
    }
    //响应文本数据
    @RequestMapping("/toText")
    @ResponseBody
    public String toText(){
        System.out.println("返回纯文本数据");
        return "responce text";
    }
    //响应POJO数据
    @RequestMapping("/toJsonPOJO")
    @ResponseBody
    public User toJsonPOJO(){
        System.out.println("返回json对象数据");
        User user = new User();
        user.setName("zhangsan");
        user.setAge(15);
        return user;
    }
    //响应POJO集合对象
    @RequestMapping("/toJsonList")
    @ResponseBody
    public List<User> toJsonList(){
        System.out.println("返回json集合数据");
        List<User> userList = new ArrayList<User>(){{
            add(new User("zhangsan", 15));
            add(new User("lisi", 16));
        }};
        return userList;
    }
}

在postman中发送形如:http://localhost:8080/springmvc/user/toJsonList,即可看到结果

4.2 @ResponseBody

名称@ResponseBody
类型方法\类注解
位置SpringMVC控制器方法定义上方和控制类上
作用设置当前控制器返回值作为响应体,
写在类上,该类的所有方法都有该注解功能
相关属性pattern:指定日期时间格式字符串

说明:

  • 写在类上就是该类下的所有方法都有@ReponseBody功能

  • 当方法上有@ReponseBody注解后

    • 方法的返回值为字符串,会将其作为文本内容直接响应给前端
    • 方法的返回值为对象,会将对象转换成JSON响应给前端
  • 内部通过一个新的接口HttpMessageConverter实现

HttpMessageConverter接口 - 类型转换器

在这里插入图片描述

实现json类型转换

5. REST风格

5.1 Rest简介

传统风格资源描述形式

  • http://localhost/user/getById?id=1 查询id为1的用户信息
  • http://localhost/user/saveUser 保存用户信息

REST风格描述形式

  • http://localhost/user/1
  • http://localhost/user

REST的优点有:

  • 隐藏资源的访问行为,无法通过地址得知对资源是何种操作
  • 书写简化

REST风格访问资源时使用行为动作区分对资源进行了何种操作

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

按照不同的请求方式代表不同的操作类型

  • 发送GET请求是用来做查询
  • 发送POST请求是用来做新增
  • 发送PUT请求是用来做修改
  • 发送DELETE请求是用来做删除

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

5.2 RESTful入门案例

增删改查代码

package org.example.controller;

@Controller
public class UserController {
    //设置当前请求方法为POST,表示REST风格中的添加操作
    @RequestMapping(value = "/users", method = RequestMethod.POST)
    @ResponseBody
    public String save(){
        System.out.println("user save...");
        return "{'module':'user save'}";
    }
    //设置当前请求方法为DELETE,表示REST风格中的删除操作
    //@PathVariable注解用于设置路径变量(路径参数),要求路径上设置对应的占位符,并且占位符名称与方法形参名称相同
    @RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable Integer id){
        System.out.println("user delete..." + id);
        return "{'module':'user delete'}";
    }
    //设置当前请求方法为PUT,表示REST风格中的修改操作
    @RequestMapping(value = "/users", method = RequestMethod.PUT)
    @ResponseBody
    public String update(@RequestBody User user){
        System.out.println("user update..."+user);
        return "{'module':'user update'}";
    }
    //设置当前请求方法为GET,表示REST风格中的查询操作
    //@PathVariable注解用于设置路径变量(路径参数),要求路径上设置对应的占位符,并且占位符名称与方法形参名称相同
    @RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
    @ResponseBody
    public String getById(@PathVariable Integer id){
        System.out.println("user getById..."+id);
        return "{'module':'user getById'}";
    }
    //设置当前请求方法为GET,表示REST风格中的查询操作
    @RequestMapping(value = "/users", method = RequestMethod.GET)
    @ResponseBody
    public String getAll(){
        System.out.println("user getAll...");
        return "{'module':'user getAll'}";
    }
}

发送请求的方式分别为

1. 增:save()
POST http://localhost:8080/springmvc/users
2. 删:delete(Integer id)
DELETE http://localhost:8080/springmvc/users/1
3. 改:update(User user)
PUT http://localhost:8080/springmvc/users
4. 查:getById(Integer id)
GET http://localhost:8080/springmvc/users/1
5. 查:getAll()
GET http://localhost:8080/springmvc/users

5.3 接收参数的三种方法

接收参数有三个注解@RequestBody@RequestParam@PathVariable

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

5.4 RESTful快速开发

package org.example.controller;

@RestController //等同于 @Controller 和 @ResponseBody 两个注解组合功能
@RequestMapping("/books")
public class BookController {
    //@RequestMapping(method = RequestMethod.POST)
    @PostMapping
    public String save(@RequestBody Book book){
        System.out.println("book save..." + book);
        return "{'module':'book 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 Book book){
        System.out.println("book update..."+book);
        return "{'module':'book update'}";
    }
    //@RequestMapping(value = "/{id}", method = RequestMethod.GET)
    @GetMapping("/{id}")
    public String getById(@PathVariable Integer id){
        System.out.println("book getById..."+id);
        return "{'module':'book getById'}";
    }
    //@RequestMapping(method = RequestMethod.GET)
    @GetMapping
    public String getAll(){
        System.out.println("book getAll...");
        return "{'module':'book getAll'}";
    }
}

RESTful风格的访问方式不变

5.5 RESTful案例

需求:

  • 列表查询,从后台返回数据,将数据展示在页面上
  • 将新增图书的数据传递到后台,并在控制台打印

这里没有做实际数据库操作,只是用了假数据

步骤1:pom.xml

<dependencies>
    <!-- 导入坐标springmvc和servlet -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- webmvc-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
    <!-- jackson -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.0</version>
    </dependency>
</dependencies>

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

步骤2:Controller类

配置类需要ServletContainersInitConfig,SpringMvcConfig,SpringConfig,配置代码见1.2节

package org.example.controller;

@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(){
        List<Book> bookList = new ArrayList<>();
        Book book1 = new Book();
        book1.setType("计算机");book1.setName("SpringMVC入门教程");book1.setDescription("小试牛刀");
        bookList.add(book1);
        Book book2 = new Book();
        book2.setType("计算机");book2.setName("SpringMVC实战教程");book2.setDescription("一代宗师");
        bookList.add(book2);
        return bookList;
    }
}

步骤3:postman测试

新增图书

在这里插入图片描述

列表查询

在这里插入图片描述

步骤4:前端资源的放行

将前端页面拷贝到项目中去

在这里插入图片描述

此时访问:http://localhost/pages/books.html,将报错
原因:在ServletContainersInitConfig中重写getServletMappings时,设置了拦截所有资源,因此报错 No mapping for GET /pages/books.html
解决方法:放行

  • SpringMvcSupport

    package org.example.config;
    
    //用于放行前端页面
    @Configuration
    public class SpringMvcSupport extends WebMvcConfigurationSupport {
        @Override
        protected void addResourceHandlers(ResourceHandlerRegistry registry) {
            //当访问/pages/下的资源时,走/pages目录下的内容
            registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
            registry.addResourceHandler("/js/**").addResourceLocations("/js/");
            registry.addResourceHandler("/css/**").addResourceLocations("/css/");
            registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
        }
    }
    
    
  • SpringMvcConfig

    package org.example.config;
    
    @Configuration
    @ComponentScan({"org.example.controller", "org.example.config"})
    @EnableWebMvc
    public class SpringMvcConfig {
    }
    

前端发送ajax请求(了解):

methods: {
	...
    //添加
    saveBook() {
        axios.post("/books", this.formData).then((res) => {

        });
    },
    //主页列表查询
    getAll() {
        axios.get("/books").then((res) => {
            this.dataList = res.data;
        });
    },
	...
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/179978.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyTorch深度学习实践第二讲线性模型

目录监督学习四步骤线性模型泛化代码作业监督学习四步骤 DataSet&#xff08;数据集&#xff09;Model&#xff08;模型选择和设计&#xff0c;例如神经网络&#xff0c;决策树等&#xff09;Training&#xff08;大部分模型都需要训练&#xff0c;都有些例如KNN不需要训练&am…

BFS(四)127. 单词接龙、433. 最小基因变化

目录 127. 单词接龙 433. 最小基因变化 127. 单词接龙 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk&#xff1a; 每一对相邻的单词只差一个字母。 对于 1 < i < k 时&am…

Qt 6.x中Qt Quick简介及示例

Qt Quick首次在Qt 4.7和Qt Creator 2.1中引入&#xff0c;是一种高级UI技术。 Qt Quick模块是用于编写QML(Qt Meta-Object Language, Qt元对象语言)应用程序的标准库。Qt QML模块提供了QML引擎(engine)和语言基础设施&#xff0c;而Qt Quick模块提供了使用QML创建用户界面…

LCD timing的理解

前言 LCD的时序,之前也有介绍过(深入裸机),但是在介绍这些参数的时候是以感性的认识去理解的,而且多少有些错误,我们以内核文档中的描述为准(Documentation/fb/framebuffer.txt),在结合全志平台来重新正确的理解这些参数。 我们在看下文档中的解释: The frame buffe…

【学习笔记】智能合约引擎

图片来源&#xff1a;https://www.researchgate.net/publication/336453428_Detecting_nondeterministic_payment_bugs_in_Ethereum_smart_contracts/figures?lo1智能合约是区块链技术的核心。我们可以根据以下公式定义智能合约智能合约事务处理和保存机制完备的状态机智能合约…

【手写 Promise 源码】第一篇 - Promise 简介

一&#xff0c;前言 上一篇&#xff0c;完成了 Promise 源码学习的目录&#xff1b; 本篇&#xff0c;主要对 Promise 进行简单的概括介绍&#xff1b; 二&#xff0c;Promise 简介 Promise 是一个类或构造函数&#xff0c;是 JS 原生提供的&#xff0c;通过实例化 Promise …

【Java】还不懂this关键字?一分钟彻底弄懂this关键字

博主简介&#xff1a;努力学习的预备程序媛一枚~博主主页&#xff1a; 是瑶瑶子啦所属专栏: Java岛冒险记【从小白到大佬之路】 前言 问题&#xff1a;为什么会存在this? 在上一篇【JavaSE】一文看懂构造器/构造方法&#xff08;Cunstructor&#xff09;中&#xff0c;我们已…

更方便Spring存储和读取对象,五大类注解、@Bean、@Autowired、@Resource

上一篇博客我们介绍了如何使用xml来引入bean对象&#xff0c;当项目多的时候&#xff0c;显然那样是比较麻烦的。现在我们只需要 个注解就可以替代了。注意&#xff1a;注解和xml可以同时使用准备工作:配置扫描路径我们需要配置 下存储对象的扫描包路径&#xff0c;只有被配置的…

利用Windows系统服务进行权限提升

提权是后渗透重要的一环节&#xff0c;如果当前获取的用户权限比较低&#xff0c;那么我们将无法访问受保护的系统资源或执行系统管理操作&#xff0c;影响后续的攻击过程。这要求我们通过各种手段将当前用户的权限进行提升&#xff0c;以满足后续攻击的要求。利用系统服务提权…

VUE2--22.11.23

VUE2一、Vue.js devtools二、Vue简介1、什么是Vue2、Vue的特性1.数据驱动视图2.双向数据绑定3.MVVM三、Vue的基本使用1、基本使用步骤四、Vue的指令与过滤器1、什么是指令2、内容渲染指令1.v-text2.{{}}3.v-html3、属性绑定指令4、事件绑定指令5、双向绑定指令6、条件渲染指令7…

【Linux】动静态库、文件的三个时间

1.文件的三个时间Access: 访问时间&#xff0c;访问的频率很高&#xff0c;所以较新的Linux都是按一定的时间间隔刷新Modify: 修改文件内容时间Change:修改文件属性时间&#xff0c;修改文件内容也会修改文件属性makefile自动编译判断文件是否为最新&#xff1a;就是按可执行程…

运动基元(一):Dubin‘s曲线【part3】

3.5 RLR RLR的第一段圆弧的曲率 k 1 = − k m a x < 0 → s i g n ( k 1 ) = − 1 k_1=-k_{max}<0\rightarrow si

Springboot图书馆图书借阅管理系统x1x74

目 录 1 概述 1 1.1课题背景及意义 1 1.2 国内外研究现状 1 1.3 本课题主要工作 2 2 系统开发环境 3 2.1 java简介 3 2.2 Mysql数据库 3 2.3 B/S结构 4 2.4 JSP技术介绍 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2操作…

机器学习sklearn笔记:LDA(线性判别分析)

1 介绍 1.有监督的降维2.投影后类内方差最小&#xff0c;类间方差最大2 推导 我们记最佳的投影向量为w&#xff0c;那么一个样例x到方向向量w上的投影可以表示为&#xff1a; 给定数据集令分别表示第i类的样本个数、样本集合、均值向量和协方差矩阵——>在投影上的均值是 —…

kafka初识

安装kafka 下载 下载window的kafka地址 window的kafka只是为了方便学习 安装地址&#xff1a;kafka.apache.org/ 安装 解压zip为文件夹 启动kafka kafka服务器的功能相当于RocketMQ中的broker&#xff0c;kafka运行还需要一个类似于命名服务器的服务。在kafka安装目录中自…

Windows10添加WebDav地址时报错“输入的文件夹无效,请选择另一个”

一、问题描述在使用Windows10添加WebDav网络地址时&#xff0c;报错“输入的文件夹无效&#xff0c;请选择另一个”&#xff0c;如下图所示&#xff1a;二、问题分析这是由于Windows10的WebDav默认只支持https协议&#xff0c;没有支持http协议导致的。三、解决办法3.1、修改注…

计算机科学领域中里程牌式的算法

计算机科学中伟大的算法前言搜索引擎的索引PageRank公钥加密 --- 用明信片传输秘密纠错码数据压缩无损压缩有损压缩数据库 --- 追求一致性的历程事务和待办事项&#xff08;预写日志记录&#xff09;数字签名用挂锁签名用指数挂锁签名RSA的安全性前言 我肯定不是一位天文学专家…

redis 消息队列方案

redis 消息队列方案 观察角度&#xff1a;消息有序&#xff0c;重复消息处理&#xff0c;消息可靠性保证 pub/sub 发布订阅机制 list集合 消息有序&#xff1a;lpush和rpop可以保证消息顺序的被消费 重复消息处理&#xff1a;list没有为消息提供唯一标识&#xff0c;需要生产者…

利用matlab求解非线性目标函数

文章目录函数介绍设置函数参数步骤结果分析函数介绍 使用fmincon函数来进行求解&#xff0c;格式为 [x,y] fmincon(f,x0,A,b,Aeq,beq,lb,ub,nonlcon,options)其中&#xff0c;f表示所求的目标函数&#xff0c;x0表示初始值&#xff0c;A,b,Aeq,beq表示线性的约束&#xff0c…

SpringBoot06:整合JDBC、Druid、MyBatis

整合JDBC 1、创建一个新的工程&#xff0c;勾选JDBC API和MySQL Driver 2、导入web启动器 3、编写yaml配置文件&#xff0c;连接数据库 spring:datasource:username: rootpassword: 123456url: jdbc:mysql://localhost:3306/mybatis?useUnicodetrue&characterEncodingut…