SpringMVC入门

SpringMVC概述

三层架构


servlet处理请求和数据的时候,存在的问题是一个servlet只能处理一个请求



因为是异步调用,所以后端不需要返回view视图,将其去除 前端如果通过异步调用的方式进行交互,后台就需要将返回的数据转换成json格式进行返回

SpringMVC主要负责的就是

controller如何接收请求和数据

如何将请求和数据转发给业务层

如何将响应数据转换成json发回到前端

介绍了这么多,对SpringMVC进行一个定义

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

灵活性强


SpringMVC入门案例

SpringMVC具体的实现流程

1.创建web工程(Maven结构)

2.设置tomcat服务器,加载web工程(tomcat插件)

3.导入坐标(SpringMVC+Servlet)

4.定义处理请求的功能类(UserController)

5.设置请求映射(配置映射关系)

6.将SpringMVC设定加载到Tomcat容器中

步骤1:创建Maven项目

步骤2:补全目录结构


步骤3:导入jar包

<?xml version="1.0" encoding="UTF-8"?>


    4.0.0

    com.itheima
    springmvc_01_quickstart
    1.0-SNAPSHOT
    war

    
        
            javax.servlet
            javax.servlet-api
            3.1.0
            provided
        
        
            org.springframework
            spring-webmvc
            5.2.10.RELEASE
        
    

    
        
            
                org.apache.tomcat.maven
                tomcat7-maven-plugin
                2.1
                
                    8888
                    /
                
            
        
    



说明:

servlet的坐标为什么需要添加provided ? scope是maven中jar包依赖作用范围的描述, 如果不设置默认是compile在在编译、运行、测试时均有效 如果运行有效的话就会和tomcat中的servlet-api包发生冲突,导致启动报错

provided代表的是该包只在编译和测试的时候用,运行的时候无效直接使用tomcat中的,就避免冲突.

步骤4:创建配置类

package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

//springmvc配置类,本质上还是一个spring配置类
@Configuration
@ComponentScan("com.itheima.controller")
public class SpringMvcConfig {
}

步骤5:创建Controller类

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

将web.xml删除,换成ServletContainersInitConfig

package com.itheima.config;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

//web容器配置类
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    //加载springmvc配置类,产生springmvc容器(本质还是spring容器)
    protected WebApplicationContext createServletApplicationContext() {
        //初始化WebApplicationContext对象
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        //加载指定配置类
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }

    //设置由springmvc控制器处理的请求映射路径
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    //加载spring配置类
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }
}

步骤7:配置Tomcat环境

IDEA配置Tomcat环境


步骤8:启动运行项目


步骤9:设置返回数据为json

如果方法直接返回字符串,springmvc会把字符串当成页面的名称在项目中进行查找 返回,因为不存在对应返回值名称的页面,所以会报404错误,找不到资源。 而我们其实是想要直接返回的是json数据,具体如何修改呢?

添加注解@ResponseBody

package com.itheima.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

//定义表现层控制器bean
@Controller
public class UserController {

    //设置映射路径为/save,即外部访问路径
    @RequestMapping("/save")
    //设置当前操作返回结果为指定json数据(本质上是一个字符串信息)
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'info':'springmvc'}";

    }


}


工作流程解析

为了更好的使用SpringMVC,我们将SpringMVC的使用过程总共分两个阶段来分析,分别是启动服务 器初始化过程和单次请求过程


启动服务器初始化过程

1. 服务器启动,执行ServletContainersInitConfig类,初始化web容器 功能类似于以前的web.xml

2. 执行createServletApplicationContext方法,创建了WebApplicationContext对象 该方法加载SpringMVC的配置类SpringMvcConfig来初始化SpringMVC的容器

3. 加载SpringMvcConfig配置类


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

扫描指定包及其子包下所有类上的注解,如Controller类上的@Controller注解

5. 加载UserController,每个@RequestMapping的名称对应一个具体的方法


此时就建立了 /save 和 save方法的对应关系

6. 执行getServletMappings方法,设定SpringMVC拦截请求的路径规则


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

单次请求过程

1. 发送请求http://localhost/save

2. web容器发现该请求满足SpringMVC拦截规则,将请求交给SpringMVC处理

3. 解析请求路径/save

4. 由/save匹配执行对应的方法save() 上面的第五步已经将请求路径和方法建立了对应关系,通过/save就能找到对应的save方法

5. 执行save()

6. 检测到有@ResponseBody直接将save()方法的返回值作为响应体返回给请求方

bean加载控制

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

业务bean(Service)

功能bean(DataSource,SqlSessionFactoryBean,MapperScannerConfigurer等)

分析清楚谁该管哪些bean以后,接下来要解决的问题是如何让Spring和SpringMVC分开加载各自的 内容。

在SpringMVC的配置类SpringMvcConfig中使用注解@ComponentScan,我们只需要将其扫描范围设 置到controller即可,如


在Spring的配置类SpringConfig中使用注解@ComponentScan ,当时扫描的范围中其实是已经包含 了controller,如:


从包结构来看的话,Spring已经多把SpringMVC的controller类也给扫描到,所以针对这个问题 该如何解决,就是咱们接下来要学习的内容。

概括的描述下咱们现在的问题就是因为功能不同,如何避免Spring错误加载到SpringMVC的bean?

针对上面的问题,解决方案也比较简单,就是:

加载Spring控制的bean的时候排除掉SpringMVC控制的bean

具体该如何排除:

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

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

方式三:不区分Spring与SpringMVC的环境,加载到同一个环境中[了解即可]

设置bean加载控制

方式一:修改Spring配置类,设定扫描范围为精准范围。

package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

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

说明:

上述只是通过例子说明可以精确指定让Spring扫描对应的包结构,真正在做开发的时候,因为Dao最 终是交给MapperScannerConfigurer对象来进行扫描处理的,我们只需要将其扫描到service包可。

方式二:修改Spring配置类,设定扫描范围为com.itheima,排除掉controller包中的bean

package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

@Configuration
//设置spring配置类加载bean时的过滤规则,当前要求排除掉表现层对应的bean
//excludeFilters属性:设置扫描加载bean时,排除的过滤规则
//type属性:设置排除规则,当前使用按照bean定义时的注解类型进行排除
//classes属性:设置排除的具体注解类,当前设置排除@Controller定义的bean
@ComponentScan(value="com.itheima",
        excludeFilters = @ComponentScan.Filter(
                type = FilterType.ANNOTATION,
                classes = Controller.class
        )
)
public class SpringConfig {
}

ANNOTATION:按照注解排除

ASSIGNABLE_TYPE:按照指定的类型过滤

ASPECTJ:按照Aspectj表达式排除,基本上不会用

REGEX:按照正则表达式排除

CUSTOM:按照自定义规则排除

大家只需要知道第一种ANNOTATION即可

请求与响应

设置映射路径

package com.itheima.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class BookController {
    //请求路径映射
    @RequestMapping("/book/save")
    @ResponseBody
    public String save(){
        System.out.println("book save ...");
        return "{'module':'book save'}";
    }
}
package com.itheima.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
//类上方配置的请求映射与方法上面配置的请求映射连接在一起,形成完整的请求映射路径
@RequestMapping("/user")
public class UserController {
    //请求路径映射
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'module':'user save'}";
    }
    //请求路径映射
    @RequestMapping("/delete")
    @ResponseBody
    public String delete(){
        System.out.println("user delete ...");
        return "{'module':'user delete'}";
    }

}

请求参数

请求路径设置好后,只要确保页面发送请求地址和后台Controller类中配置的路径一致,就可以接 收到前端的请求,接收到请求后,如何接收页面传递的参数?

关于请求参数的传递与接收是和请求方式有关系的,目前比较常见的两种请求方式为:

GET发送单个参数

发送请求与参数:

http://localhost/commonParam?name=itcast

接收参数:


//普通参数:请求参数与形参名称对应即可完成参数传递
@RequestMapping("/commonParam")
@ResponseBody
public String commonParam(String name ){
    System.out.println("普通参数传递 name ==> "+name);
    return "{'module':'common param'}";
}

GET发送多个参数

发送请求与参数:

http://localhost/commonParam?name=itcast&age=15

接收参数:


//普通参数:请求参数与形参名称对应即可完成参数传递
@RequestMapping("/commonParam")
@ResponseBody
public String commonParam(String name ,int age){
    System.out.println("普通参数传递 name ==> "+name);
    System.out.println("普通参数传递 age ==> "+age);
    return "{'module':'common param'}";
}

GET请求中文乱码

出现乱码的原因相信大家都清楚,Tomcat8.5以后的版本已经处理了中文乱码的问题,但是IDEA中的Tomcat插件目前只到Tomcat7,所以需要修改pom.xml来解决GET请求中文乱码问题

UTF-8


    
        
            org.apache.tomcat.maven
            tomcat7-maven-plugin
            2.1
            
                8999
                /
                UTF-8

            
        
    

POST发送参数

发送请求与参数:


接收参数:

和GET一致,不用做任何修改

//普通参数:请求参数与形参名称对应即可完成参数传递
@RequestMapping("/commonParam")
@ResponseBody
public String commonParam(String name ,int age){
    System.out.println("普通参数传递 name ==> "+name);
    System.out.println("普通参数传递 age ==> "+age);
    return "{'module':'common param'}";
}

POST请求中文乱码

解决方案:配置过滤器

package com.itheima.config;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.servlet.Filter;

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};
    }
}

CharacterEncodingFilter是在spring-web包中,所以用之前需要导入对应的jar包。

五种类型参数传递

普通参数


如果形参与地址参数名不一致该如何解决?

解决方案:使用@RequestParam注解

//普通参数:请求参数名与形参名不同时,使用@RequestParam注解关联请求参数名称与形参名称之间的关系
@RequestMapping("/commonParamDifferentName")
@ResponseBody
public String commonParamDifferentName(@RequestParam("name") String userName , int age){
    System.out.println("普通参数传递 userName ==> "+userName);
    System.out.println("普通参数传递 age ==> "+age);
    return "{'module':'common param different name'}";
}

注意:写上@RequestParam注解框架就不需要自己去解析注入,能提升框架处理性能

POJO数据类型

简单数据类型一般处理的是参数个数比较少的请求,如果参数比较多,那么后台接收参数的时候就比 较复杂,这个时候我们可以考虑使用POJO数据类型。

此时需要使用前面准备好的POJO类,先来看下User

package com.itheima.domain;

public class User {
    private String name;
    private int age;

    private Address address;


    @Override
    public String toString() {
        return "User{" +
                "name='" + name + ''' +
                ", age=" + age +
                ", 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;
    }
}

发送请求和参数:


后台接收参数:

//POJO参数:请求参数与形参对象中的属性对应即可完成参数传递
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
    System.out.println("pojo参数传递 user ==> "+user);
    return "{'module':'pojo param'}";
}

注意:

如果POJO对象中嵌套了其他的POJO类,如


public class Address {
    private String province;
    private String city;
    //setter...getter...略

}

public class User {
    private String name;
    private int age;
    private Address address;
    //setter...getter...略

}

发送请求和参数:


后台接收参数

//嵌套POJO参数:嵌套属性按照层次结构设定名称即可完成参数传递
@RequestMapping("/pojoContainPojoParam")
@ResponseBody
public String pojoContainPojoParam(User user){
    System.out.println("pojo嵌套pojo参数传递 user ==> "+user);
    return "{'module':'pojo contain pojo param'}";
}

请求参数key的名称要和POJO中属性的名称一致,否则无法封装

数组类型参数

举个简单的例子,如果前端需要获取用户的爱好,爱好绝大多数情况下都是多个,如何发送请求数据 和接收数据呢?


//数组参数:同名请求参数可以直接映射到对应名称的形参数组对象中
@RequestMapping("/arrayParam")
@ResponseBody
public String arrayParam(String[] likes){
    System.out.println("数组参数传递 likes ==> "+ Arrays.toString(likes));
    return "{'module':'array param'}";
}

集合类型参数


数组能接收多个值,那么集合是否也可以实现这个功能呢?

发送请求和参数


:

后台接收参数:

//集合参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据
@RequestMapping("/listParam")
@ResponseBody
public String listParam(@RequestParam List likes){
    System.out.println("集合参数传递 likes ==> "+ likes);
    return "{'module':'list param'}";
}

SpringMVC将List看做是一个POJO对象来处理,将其创建一个对象并准备把前端的数 据封装到对象中.

JSON数据传输参数

前面我们说过,现在比较流行的开发方式为异步调用。前后台以异步方式进行交换,传输的数据使用 的是JSON,所以前端如果发送的是JSON数据,后端该如何接收?

对于JSON数据类型,我们常见的有三种:

对于上述数据,前端如何发送,后端如何接收?

JSON普通数组

步骤1:pom.xml添加依赖

SpringMVC默认使用的是jackson来处理json的转换,所以需要在pom.xml添加jackson依赖


    com.fasterxml.jackson.core
    jackson-databind
    2.9.0

步骤2:PostMan发送JSON数据


步骤3:开启SpringMVC注解支持

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

package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import javax.servlet.Filter;
import javax.servlet.annotation.WebFilter;

@Configuration
@ComponentScan("com.itheima.controller")
//开启json数据类型自动转换
@EnableWebMvc
public class SpringMvcConfig {
}

步骤4:参数前添加@RequestBody

//集合参数:json格式
//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc
//2.使用@RequestBody注解将外部传递的json数组数据映射到形参的集合对象中作为数据
@RequestMapping("/listParamForJson")
@ResponseBody
public String listParamForJson(@RequestBody List likes){
    System.out.println("list common(json)参数传递 list ==> "+likes);
    return "{'module':'list common for json param'}";
}

步骤5:启动运行程序


JSON普通数组的数据就已经传递完成,下面针对JSON对象数据和JSON对象数组的数据该如何传递呢?

JSON对象数据

我们会发现,只需要关注请求和数据如何发送?后端数据如何接收?

请求和数据的发送:

{

"name":"itcast",

"age":15

}


后端接收数据:

//POJO参数:json格式
//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc
//2.使用@RequestBody注解将外部传递的json数据映射到形参的实体类对象中,要求属性名称一一对应
@RequestMapping("/pojoParamForJson")
@ResponseBody
public String pojoParamForJson(@RequestBody User user){
    System.out.println("pojo(json)参数传递 user ==> "+user);
    return "{'module':'pojo for json param'}";
}

启动程序访问测试


说明:

address为null的原因是前端没有传递数据给后端。

如果想要address也有数据,我们需求修改前端传递的数据内容:

{

"name":"itcast",

"age":15,

"address":

{

"province":"beijing",

"city":"beijing"

}

}

JSON对象数组

集合中保存多个POJO该如何实现?

请求和数据的发送:

[

{"name":"itcast","age":15},

{"name":"itheima","age":12}

]


后端接收数据:

//集合参数:json格式
//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc
//2.使用@RequestBody注解将外部传递的json数组数据映射到形参的保存实体类对象的集合对象中,要求属性名称一一对应
@RequestMapping("/listPojoParamForJson")
@ResponseBody
public String listPojoParamForJson(@RequestBody List list){
    System.out.println("list pojo(json)参数传递 list ==> "+list);
    return "{'module':'list pojo for json param'}";
}

小结

SpringMVC接收JSON数据的实现步骤为:

(1)导入jackson包

(2)使用PostMan发送JSON数据

(3)开启SpringMVC注解驱动,在配置类上添加@EnableWebMvc注解

(4)Controller方法的参数前添加@RequestBody注解

@RequestBody与@RequestParam区别

区别

@RequestParam用于接收url地址传参,表单传参【application/x-www-formurlencoded】

@RequestBody用于接收json数据【application/json】

@RequestMapping("/listPojoParamForJson")

@ResponseBody

public String listPojoParamForJson(@RequestBody List<User> list){

System.out.println("list pojo(json)参数传递 list ==> "+list);

return "{'module':'list pojo for json param'}";

}


应用

日期类型参数传递

前面我们处理过简单数据类型、POJO数据类型、数组和集合数据类型以及JSON数据类型,接下来我们 还得处理一种开发中比较常见的一种数据类型,日期类型

日期类型比较特殊,因为对于日期的格式有N多中输入方式,比如: 2088-08-18 2088/08/18 08/18/2088 ......

针对这么多日期格式

,SpringMVC该如何接收,它能很好的处理日期类型数据么?

步骤1:编写方法接收日期数据

在UserController类中添加方法,把参数设置为日期类型

//日期参数
//使用@DateTimeFormat注解设置日期类型数据格式,默认格式yyyy/MM/dd
@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("参数传递 date1(yyyy-MM-dd) ==> "+date1);
    System.out.println("参数传递 date2(yyyy/MM/dd HH:mm:ss) ==> "+date2);
    return "{'module':'data param'}";
}

SpringMVC默认支持的字符串转日期的格式为yyyy/MM/dd,如果想使用其他格式,需要使用@DateTimeFormat。

响应

对于响应,主要就包含两部分内容:

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@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 toJsonList(){
        System.out.println("返回json集合数据");
        User user1 = new User();
        user1.setName("传智播客");
        user1.setAge(15);

        User user2 = new User();
        user2.setName("黑马程序员");
        user2.setAge(12);

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

        return userList;
    }
}

Rest风格

REST简介

REST(Representational State Transfer),表现形式状态转换,它是一种软件架构风格

当我们想表示一个网络资源的时候,可以使用两种方式:

传统风格资源描述形式

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

http://localhost/user/saveUser 保存用户信息

REST风格描述形式

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

传统方式一般是一个请求url对应一种操作,这样做不仅麻烦,也不安全,因为会程序的人读取了你的 请求url地址,就大概知道该url实现的是一个什么样的操作。 查看REST风格的描述,你会发现请求地址变的简单了,并且光看请求URL并不是很能猜出来该URL的 具体功能 所以REST的优点有:

隐藏资源的访问行为,无法通过地址得知对资源是何种操作 书写简化 但是我们的问题也随之而来了,一个相同的url地址即可以是新增也可以是修改或者查询,那么到底我 们该如何区分该请求到底是什么操作呢?

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

请求的方式比较多,但是比较常用的就4种,分别是GET , POST , PUT , DELETE。

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

发送GET请求是用来做查询

发送POST请求是用来做新增发送

PUT请求是用来做修改

发送DELETE请求是用来做删除

清楚了什么是REST风格后,我们后期会经常提到一个概念叫RESTful,那什么又是RESTful呢?

根据REST风格对资源进行访问称为RESTful。 后期我们在进行开发的过程中,大多是都是遵从REST风格来访问我们的后台服务,所以可以说咱们以 后都是基于RESTful来进行开发的。

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@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'}";
    }

}









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

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

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

    @RequestMapping
    @ResponseBody
    public String getAll(){
        System.out.println("user getAll...");
        return "{'module':'user getAll'}";
    }
    */
package com.itheima.controller;

import com.itheima.domain.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

//@Controller
//@ResponseBody配置在类上可以简化配置,表示设置当前每个方法的返回值都作为响应体
//@ResponseBody
@RestController     //使用@RestController注解替换@Controller与@ResponseBody注解,简化书写
@RequestMapping("/books")
public class BookController {

    //    @RequestMapping( method = RequestMethod.POST)
    @PostMapping        //使用@PostMapping简化Post请求方法对应的映射配置
    public String save(@RequestBody Book book){
        System.out.println("book save..." + book);
        return "{'module':'book save'}";
    }

    //    @RequestMapping(value = "/{id}" ,method = RequestMethod.DELETE)
    @DeleteMapping("/{id}")     //使用@DeleteMapping简化DELETE请求方法对应的映射配置
    public String delete(@PathVariable Integer id){
        System.out.println("book delete..." + id);
        return "{'module':'book delete'}";
    }

    //    @RequestMapping(method = RequestMethod.PUT)
    @PutMapping         //使用@PutMapping简化Put请求方法对应的映射配置
    public String update(@RequestBody Book book){
        System.out.println("book update..."+book);
        return "{'module':'book update'}";
    }

    //    @RequestMapping(value = "/{id}" ,method = RequestMethod.GET)
    @GetMapping("/{id}")    //使用@GetMapping简化GET请求方法对应的映射配置
    public String getById(@PathVariable Integer id){
        System.out.println("book getById..."+id);
        return "{'module':'book getById'}";
    }

    //    @RequestMapping(method = RequestMethod.GET)
    @GetMapping             //使用@GetMapping简化GET请求方法对应的映射配置
    public String getAll(){
        System.out.println("book getAll...");
        return "{'module':'book getAll'}";
    }
}


新增

//设置当前请求方法为POST,表示REST风格中的添加操作
@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String save(){
    System.out.println("user save...");
    return "{'module':'user save'}";
}
//    @RequestMapping( method = RequestMethod.POST)
@PostMapping        //使用@PostMapping简化Post请求方法对应的映射配置
public String save(@RequestBody Book book){
    System.out.println("book save..." + book);
    return "{'module':'book save'}";
}

删除

前端发送请求的时候使用: http://localhost/users/1 ,路径中的1就是我们想要传递的参数。

后端获取参数,需要做如下修改:

//设置当前请求方法为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'}";
}
//    @RequestMapping(value = "/{id}" ,method = RequestMethod.DELETE)
@DeleteMapping("/{id}")     //使用@DeleteMapping简化DELETE请求方法对应的映射配置
public String delete(@PathVariable Integer id){
    System.out.println("book delete..." + id);
    return "{'module':'book delete'}";
}


如果有多个参数需要传递该如何编写?

前端发送请求的时候使用: http://localhost/users/1/tom ,路径中的1和tom就是我们想要传递的 两个参数。 后端获取参数,需要做如下修改:

@Controller

public class UserController {
    //设置当前请求方法为DELETE,表示REST风格中的删除操作

    @RequestMapping(value = "/users/{id}/{name}",method =

            RequestMethod.DELETE)
    @ResponseBody

    public String delete(@PathVariable Integer id,@PathVariable String name)
    {
        System.out.println("user delete..." + id+","+name);
        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'}";
}

访问该方法使用 PUT: http://localhost/users


根据ID查询

//设置当前请求方法为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'}";
}

小结

RESTful入门案例,我们需要学习的内容如下:

(1)设定Http请求动作(动词)

@RequestMapping(value="",method = RequestMethod.POST|GET|PUT|DELETE)

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

@RequestMapping(value="/users/{id}",method = RequestMethod.DELETE)

@ReponseBody public String delete(@PathVariable Integer id){ }

关于接收参数,我们学过三个注解@RequestBody、@RequestParam、@PathVariable ,这三个注解 之间的区别和应用分别是什么?

区别

@RequestParam用于接收url地址传参或表单传参

@RequestBody用于接收json数据

@PathVariable用于接收路径参数,使用{参数名称}描述路径参数

应用

后期开发中,发送请求参数超过1个时,以json格式为主,@RequestBody应用较广

如果发送非json格式数据,选用@RequestParam接收请求参数

采用RESTful进行开发,当参数数量较少时,例如1个,可以采用@PathVariable接收请求路 径变量,通常用于传递id值.

SpringMVC需要将静态资源进行放行。

package com.itheima.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

@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/");
    }
}

该配置类是在config目录下,SpringMVC扫描的是controller包,所以该配置类还未生效,要 想生效需要将SpringMvcConfig配置类进行修改

@Configuration
@ComponentScan({"com.itheima.controller","com.itheima.config"})

@EnableWebMvc

public class SpringMvcConfig {
}
 

或者



@Configuration
@ComponentScan("com.itheima")

@EnableWebMvc

public class SpringMvcConfig {
}
展开阅读全文

页面更新:2024-04-30

标签:注解   数组   路径   入门   加载   对象   名称   参数   类型   方法   数据

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top