SpringBoot Web请求响应

前言

之前我们基于SpringBoot的方式开发了一个web应用,浏览器发起请求 /hello 后 ,给浏览器返回字符串 “Hello World ~”。

在这里插入图片描述

其实是我们在浏览器发起请求,请求了我们的后端web服务器(也就是内置的Tomcat)。而我们在开发web程序时呢,定义了一个控制器类Controller,请求会被部署在Tomcat中的Controller接收,然后Controller再给浏览器一个响应,响应一个字符串 “Hello World”。 而在请求响应的过程中是遵循HTTP协议的。

其实在Tomcat这类Web服务器中,是不识别我们自己定义的Controller的。但是Tomcat是一个Servlet容器,是支持Serlvet规范的,所以呢,在tomcat中是可以识别 Servlet程序的。 那我们所编写的XxxController 是如何处理请求的,又与Servlet之间有什么联系呢?

其实呢,在SpringBoot进行web程序开发时,它内置了一个核心的Servlet程序DispatcherServlet,称之为 核心控制器。 DispatcherServlet 负责接收页面发送的请求,然后根据执行的规则,将请求再转发给后面的请求处理器Controller,请求处理器处理完请求之后,最终再由DispatcherServlet给浏览器响应数据。

请添加图片描述

那将来浏览器发送请求,会携带请求数据,包括:请求行、请求头;请求到达tomcat之后,tomcat会负责解析这些请求数据,然后呢将解析后的请求数据会传递给Servlet程序的HttpServletRequest对象,那也就意味着 HttpServletRequest 对象就可以获取到请求数据。 而Tomcat,还给Servlet程序传递了一个参数 HttpServletResponse,通过这个对象,我们就可以给浏览器设置响应数据 。




请求

本章节主要讲解如何接收页面传递过来的请求数据。

Postman

由于前后端分离,对我们后端技术人员来讲,在开发过程中,是没有前端页面的,那我们怎么测试自己所开发的程序呢?

方式1:像之前SpringBoot入门案例中一样,直接使用浏览器。在浏览器中输入地址,测试后端程序。

弊端:在浏览器地址栏中输入地址这种方式都是GET请求,如何我们要用到POST请求怎么办呢?
要解决POST请求,需要程序员自己编写前端代码(比较麻烦)

方式2:使用专业的接口测试工具(我们使用Postman工具)

Postman使用

在这里插入图片描述

Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。
可以模拟浏览器向后端服务器发起任何形式(如:get、post)的HTTP请求。
使用Postman还可以在发起请求时,携带一些请求参数、请求头等信息。

登录之后可以创建工作空间:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

创建请求:

在这里插入图片描述

点击"Save",可以保存当前请求

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述




简单参数

简单参数:在向服务器发起请求时,向服务器传递的是一些普通的请求数据。

在这里插入图片描述

在后端程序中,如何接收传递过来的普通参数数据呢?
在这里讲解两种方式:

  1. 原始方式
  2. SpringBoot方式

原始方式接收普通参数

这种方式仅做了解,开发不常用。

在原始的Web程序当中,需要通过Servlet中提供的API:HttpServletRequest(请求对象),获取请求的相关信息。比如获取请求参数:

Tomcat接收到http请求时:把请求的相关信息封装到HttpServletRequest对象中

在Controller中,我们要想获取Request对象,可以直接在方法的形参中声明
HttpServletRequest 对象。然后就可以通过该对象来获取请求信息:

@RestController
public class RequestController {
    //原始方式
    @RequestMapping("/simpleParam")
    public String simpleParam(HttpServletRequest request) {
// http://localhost:8080/simpleParam?name=Tom&age=10
// 请求参数: name=Tom&age=10 (有2个请求参数)
// 第1个请求参数: name=Franklin 参数名:name,参数值:Franklin
// 第2个请求参数: age=10 参数名:age , 参数值:10
        String name = request.getParameter("name");//name就是请求参数名
        String ageStr = request.getParameter("age");//age就是请求参数名
        int age = Integer.parseInt(ageStr);//需要手动进行类型转换
        System.out.println(name + " : " + age);
        return "OK";
    }
}
//根据指定的参数名获取请求参数的数据值
String request.getParameter("参数名")

请添加图片描述

请添加图片描述



SpringBoot方式接收普通参数

在Springboot的环境中,对原始的API进行了封装,接收参数的形式更加简单。 如果是简单参数,参数名与形参变量名相同,定义同名的形参即可接收参数。

@RestController
public class RequestController {
    // http://localhost:8080/simpleParam?name=Tom&age=10
// 第1个请求参数: name=Franklin 参数名:name,参数值:Franklin
// 第2个请求参数: age=10 参数名:age , 参数值:10
//springboot方式
    @RequestMapping("/simpleParam")
    public String simpleParam(String name , Integer age ){//形参名和请求参数名保持一致
        System.out.println(name+" : "+age);
        return "OK";
    }
}

postman测试( GET 请求):

请添加图片描述

postman测试( POST请求 ):

请添加图片描述

结论:不论是GET请求还是POST请求,对于简单参数来讲,只要保证请求参数名和Controller方法中的形参名保持一致,就可以获取到请求参数中的数据值。




参数名不一致问题 @RequestParam

如果方法形参名称与请求参数名称不一致,controller方法中的形参还能接收到请求参数值吗?

@RestController
public class RequestController {
    // http://localhost:8080/simpleParam?name=Tom&age=20
// 请求参数名:name
//springboot方式
    @RequestMapping("/simpleParam")
    public String simpleParam(String username , Integer age ){//请求参数名和形参名不相同
        System.out.println(username+" : "+age);
        return "OK";
    }
}

答案:运行没有报错。 controller方法中的username值为:null,age值为20

结论:对于简单参数来讲,请求参数名和controller方法中的形参名不一致时,无法接收到请求
数据

那么如果我们开发中,遇到了这种请求参数名和controller方法中的形参名不相同,怎么办?
解决方案:可以使用Spring提供的@RequestParam注解完成映射。
在方法形参前面加上 @RequestParam 然后通过value属性执行请求参数名,从而完成映射。代码如下:

@RestController
public class RequestController {
    // http://localhost:8080/simpleParam?name=Tom&age=20
// 请求参数名:name
//springboot方式
    @RequestMapping("/simpleParam")
    public String simpleParam(@RequestParam("name") String username
            , Integer age ){
        System.out.println(username+" : "+age);
        return "OK";
    }
}

注意:
@RequestParam中的required属性默认为true(默认值也是true),代表该请求参数必须传递,如果不传递将报错、

在这里插入图片描述

如果该参数是可选的,可以将required属性设置为false:

@RequestMapping("/simpleParam")
    public String simpleParam(@RequestParam(name = "name", required =
            false) String username, Integer age){
        System.out.println(username+ ":" + age);
        return "OK";
    }



实体参数

在使用简单参数做为数据传递方式时,前端传递了多少个请求参数,后端controller方法中的形参就要书写多少个。如果请求参数比较多,通过上述的方式一个参数一个参数的接收,会比较繁琐。

此时,我们可以考虑将请求参数封装到一个实体类对象中。 要想完成数据封装,需要遵守如下规则:
请求参数名与实体类的属性名相同

在这里插入图片描述

简单实体参数

定义实体类:

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Controller方法:

@RestController
public class RequestController {
    //实体参数:简单实体对象
    @RequestMapping("/simplePojo")
    public String simplePojo(User user) {
        System.out.println(user);
        return "OK";
    }
}

Postman测试参数名和实体类属性名一致时正常输出,参数名和实体类属性名不一致时,不一致的参数名输出的是null。



复杂实体对象

复杂实体对象指的是,在实体类中有一个或多个属性,也是实体对象类型的。如下:
User类中有一个Address类型的属性(Address是一个实体类)

在这里插入图片描述

复杂实体对象的封装,需要遵守如下规则:
请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套实体类属性参数。

定义POJO实体类,Address实体类:

public class Address {
    private String province;
    private String city;

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "Address{" +
                "province='" + province + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}

User实体类

public class User {
    private String name;
    private Integer age;
    private Address address; //地址对象
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }
}

Controller方法:

@RestController
public class RequestController {
    //实体参数:复杂实体对象
    @RequestMapping("/complexPojo")
    public String complexPojo(User user){
        System.out.println(user);
        return "OK";
    }
}

Postman测试:

在这里插入图片描述




数组集合参数

数组集合参数的使用场景:在HTML的表单中,有一个表单项是支持多选的(复选框),可以提交选择的多个值。

在这里插入图片描述

实多个值也是一个一个的提交:

在这里插入图片描述

后端程序接收上述多个值的方式有两种:

  1. 数组
  2. 集合

数组参数

数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数

在这里插入图片描述

Controller方法:

@RestController
public class RequestController {
    //数组集合参数
    @RequestMapping("/arrayParam")
    public String arrayParam(String[] hobby){
        System.out.println(Arrays.toString(hobby));
        return "OK";
    }
}

Postman测试:
在前端请求时,有两种传递形式:
方式一: xxxxxxxxxx?hobby=game&hobby=java

在这里插入图片描述

方式二:xxxxxxxxxxxxx?hobby=game,java

在这里插入图片描述



集合参数 @RequestParam

集合参数:请求参数名与形参集合对象名相同且请求参数为多个,需要使用@RequestParam 绑定参数关系

默认情况下,请求中参数名相同的多个值,是封装到数组。如果要封装到集合,要使用@RequestParam绑定参数关系

在这里插入图片描述

Controller方法:

@RestController
public class RequestController {
    //数组集合参数
    @RequestMapping("/listParam")
    public String listParam(@RequestParam List<String> hobby){
        System.out.println(hobby);
        return "OK";
    }
}

Postman测试:
方式一: xxxxxxxxxx?hobby=game&hobby=java

在这里插入图片描述

方式二:xxxxxxxxxxxxx?hobby=game,java

在这里插入图片描述




日期参数

在一些特殊的需求中,可能会涉及到日期类型数据的封装。比如,如下需求:

在这里插入图片描述

因为日期的格式多种多样(如:2022-12-12 10:05:45 、2022/12/12 10:05:45),那么对于日期类型的参数在进行封装的时候,需要通过@DateTimeFormat注解,以及其pattern属性来设置日期的格式:

在这里插入图片描述

@DateTimeFormat注解的pattern属性中指定了哪种日期格式,前端的日期参数就必须按照指定的格式传递。
后端controller方法中,需要使用Date类型或LocalDateTime类型,来封装传递的参数。

Controller方法:

@RestController
public class RequestController {
    //数组集合参数
    @RequestMapping("/listParam")
    public String listParam(@RequestParam List<String> hobby) {
        System.out.println(hobby);
        return "OK";
    }

    //日期时间参数
    @RequestMapping("/dateParam")
    public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime) {
        System.out.println(updateTime);
        return "OK";
    }
}

Postman测试:

在这里插入图片描述




JSON参数 @RequestBody

在前后端进行交互时,如果是比较复杂的参数,前后端通过使用JSON格式的数据进行传输。 (JSON是开发中最常用的前后端数据交互方式)

Postman如何发送JSON格式数据:

在这里插入图片描述

服务端Controller方法如何接收JSON格式数据:

1.传递json格式的参数,在Controller中会使用实体类进行封装。
2.封装规则:JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数。需要使用@RequestBody标识。

@RequestBody注解:将JSON数据映射到形参的实体类对象中(JSON中的key和实体类中的属性名保持一致)

在这里插入图片描述

上图实体类省略了GET , SET 方法。Controller方法:

@RestController
public class RequestController {
    //JSON参数
    @RequestMapping("/jsonParam")
    public String jsonParam(@RequestBody User user){
        System.out.println(user);
        return "OK";
    }
}

Postman测试:

在这里插入图片描述

经测试GET和POST命令都可以,但是Postman上的数据类型必须从text改成json:

请添加图片描述




路径参数 @PathVariable

传统的开发中请求参数是放在请求体(POST请求)传递或跟在URL后面通过?key=value的形式传递(GET请求)。

在这里插入图片描述

在现在的开发中,经常还会直接在请求的URL中传递参数。例如:

http://localhost:8080/user/1
http://localhost:880/user/1/0

上述的这种传递请求参数的形式称之为:路径参数。

前端:通过请求URL直接传递参数
后端:使用{…}来标识该路径参数,需要使@PathVariable获取路径参数

在这里插入图片描述

Controller方法:

@RestController
public class RequestController {
    //路径参数
    @RequestMapping("/path/{id}")
    public String pathParam(@PathVariable Integer id){
        System.out.println(id);
        return "OK";
    }
}

Postman测试:

在这里插入图片描述




传递多个路径参数:
Controller方法:

@RestController
public class RequestController {
    //路径参数
    @RequestMapping("/path/{id}/{name}")
    public String pathParam2(@PathVariable Integer id, @PathVariable
    String name){
        System.out.println(id+ " : " +name);
        return "OK";
    }
}

Postman:

在这里插入图片描述




响应

Controller程序除了接收请求外,还可以进行响应。

@ResponseBody

在我们前面所编写的controller方法中,都已经设置了响应数据。

在这里插入图片描述

controller方法中的return的结果,怎么就可以响应给浏览器呢?因为我们使用了@ResponseBody注解。

但是在我们所书写的Controller中,只在类上添加了@RestController注解、方法添加了@RequestMapping注解,并没有使用@ResponseBody注解,怎么给浏览器响应呢?

我们前面说过@RestController代表该类是请求处理类,其是一个组合注解:

@RestController = @Controller + @ResponseBody

可以看一下@RestController的源码:

@Target({ElementType.TYPE})  //元注解(修饰注解的注解)
@Retention(RetentionPolicy.RUNTIME)  //元注解
@Documented  //元注解
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

@ResponseBody注解:

类型:方法注解、类注解
位置:书写在Controller方法上或类上
作用:将方法返回值直接响应给浏览器
如果返回值类型是实体对象/集合,将会转换为JSON格式后在响应给浏览器


下面我们来测试下响应数据:

@RestController
public class ResponseController {
    //响应字符串
    @RequestMapping("/hello")
    public String hello(){
        System.out.println("Hello World ~");
        return "Hello World ~";
    }
    //响应实体对象
    @RequestMapping("/getAddr")
    public Address getAddr(){
        Address addr = new Address();//创建实体类对象
        addr.setProvince("广东");
        addr.setCity("深圳");
        return addr;
    }
    //响应集合数据
    @RequestMapping("/listAddr")
    public List<Address> listAddr(){
        List<Address> list = new ArrayList<>();//集合对象
        Address addr = new Address();
        addr.setProvince("广东");
        addr.setCity("深圳");
        Address addr2 = new Address();
        addr2.setProvince("陕西");
        addr2.setCity("西安");
        list.add(addr);
        list.add(addr2);
        return list;
    }
}

在服务端响应了一个对象或者集合,那私前端获取到的数据是什么样子的呢?我们使用postman发送请求来测试下。测试效果如下,可以看到返回的是JSON:

在这里插入图片描述

在这里插入图片描述




统一响应结果

前面所编写的这些Controller方法中,返回值各种各样,没有任何的规范。

在这里插入图片描述

在真实的项目开发中,无论是哪种方法,我们都会定义一个统一的返回结果。前端:只需要按照统一格式的返回结果进行解析(仅一种解析方案),就可以拿到数据。方案如下:

在这里插入图片描述

定义在一个实体类Result来包含以上信息。代码如下:

public class Result {
    private Integer code;//响应码,1 代表成功; 0 代表失败
    private String msg; //响应码 描述字符串

    private Object data; //返回的数据

    public Result() {
    }

    public Result(Integer code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    //增删改 成功响应(不需要给前端返回数据)
    public static Result success() {
        return new Result(1, "success", null);
    }

    //查询 成功响应(把查询结果做为返回数据响应给前端)
    public static Result success(Object data) {
        return new Result(1, "success", data);
    }

    //失败响应
    public static Result error(String msg) {
        return new Result(0, msg, null);
    }
}

改造Controller:

@RestController
public class ResponseController {
    //响应统一格式的结果
    @RequestMapping("/hello")
    public Result hello(){
        System.out.println("Hello World ~");
//return new Result(1,"success","Hello World ~");
        return Result.success("Hello World ~");
    }
    //响应统一格式的结果
    @RequestMapping("/getAddr")
    public Result getAddr(){
        Address addr = new Address();
        addr.setProvince("广东");
        addr.setCity("深圳");
        return Result.success(addr);
    }
    //响应统一格式的结果
    @RequestMapping("/listAddr")
    public Result listAddr(){
        List<Address> list = new ArrayList<>();
        Address addr = new Address();
        addr.setProvince("广东");
        addr.setCity("深圳");
        Address addr2 = new Address();
        addr2.setProvince("陕西");
        addr2.setCity("西安");
        list.add(addr);
        list.add(addr2);
        return Result.success(list);
    }
}

Postman测试:

在这里插入图片描述

在这里插入图片描述




请求响应案例

通过一个案例,来加强对请求响应的学习

案例需求与准备工作

需求:加载并解析xml文件中的数据,完成数据处理,并在页面展示

在这里插入图片描述

案例准备:

  1. XML文件
    已经准备好(emp.xml),直接导入进来,放在 src/main/resources目录下
  2. 工具类
    已经准备好解析XML文件的工具类,无需自己实现
    直接在创建一个包 com.itheima.utils ,然后将工具类拷贝进来
  3. 前端页面资源
    已经准备好,直接拷贝进来,放在src/main/resources下的static目录下

Springboot项目的静态资源(html,css,js等前端资源)默认存放目录为:classpath:/static、 classpath:/public、 classpath:/resources

在SpringBoot项目中,静态资源默认可以存放的目录:
classpath:/static/
classpath:/public/
classpath:/resources/
classpath:/META-INF/resources/

classpath:
代表的是类路径,在maven的项目中,其实指的就是 src/main/resources 或者
src/main/java,但是java目录是存放java代码的,所以相关的配置文件及静态资源文
档,就放在 src/main/resources下。

案例实现

  1. 在pom.xml文件中引入dom4j的依赖,用于解析XML文件
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>

2.引入资料中提供的:解析XML的工具类XMLParserUtils、实体类Emp、XML文件emp.xml

在这里插入图片描述

3.引入资料中提供的静态页面文件,放在resources下的static目录下

在这里插入图片描述

  1. 创建EmpController类,编写Controller程序,处理请求,响应数据

在这里插入图片描述

Contriller代码:

@RestController
public class EmpController {
    @RequestMapping("/listEmp")
    public Result list() {
        //1. 加载并解析emp.xml
        String file =
                this.getClass().getClassLoader().getResource("emp.xml").getFile();
        //System.out.println(file);
        List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
        //2. 对数据进行转换处理 - gender, job
        empList.stream().forEach(emp -> {
            //处理 gender 1: 男, 2: 女
            String gender = emp.getGender();
            if ("1".equals(gender)) {
                emp.setGender("男");
            } else if ("2".equals(gender)) {
                emp.setGender("女");
            }
            //处理job - 1: 讲师, 2: 班主任 , 3: 就业指导
            String job = emp.getJob();
            if ("1".equals(job)) {
                emp.setJob("讲师");
            } else if ("2".equals(job)) {
                emp.setJob("班主任");
            } else if ("3".equals(job)) {
                emp.setJob("就业指导");
            }
        });
        //3. 响应数据
        return Result.success(empList);
    }
}

ps:

String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
这个语句用到了类加载器(getClassLoader())来获取emp.xml,什么原理呢?

在Java的resources文件夹src/main/resources文件夹下的内容会被打包到生成的JAR(或者WAR)文件中,因此这些资源文件会被ClassLoader加载。

在我们的代码中,this.getClass().getClassLoader().getResource("emp.xml").getFile() 这句代码的作用是通过类加载器获取emp.xml文件的路径。
这里的getClassLoader()方法是java.lang.Class类的一个方法,用于获取类的ClassLoader。
getResource("emp.xml")方法会在类路径下查找名为emp.xml的文件,并返回一个表示该资源的URL对象。
最后,getFile()方法获取该URL的文件表示形式,即文件的路径。

由于emp.xml位于resources文件夹下,它会被编译到类路径中。因此,通过类加载器就可以获取到这个文件的路径。
这种方式通常用于获取类路径下的配置文件、模板文件等资源。
当应用程序打包成可执行的JAR文件时,这种方式仍然适用,因为resources文件夹中的内容会被包含在JAR文件中,ClassLoader可以正确地加载这些资源。


XmlParserUtils的代码是老师写的提供的,也贴在这里,以供学习

package com.example.springbootwebquickstart1.utils;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class XmlParserUtils {

    public static <T> List<T> parse(String file , Class<T> targetClass)  {
        ArrayList<T> list = new ArrayList<T>(); //封装解析出来的数据
        try {
            //1.获取一个解析器对象
            SAXReader saxReader = new SAXReader();
            //2.利用解析器把xml文件加载到内存中,并返回一个文档对象
            Document document = saxReader.read(new File(file));
            //3.获取到根标签
            Element rootElement = document.getRootElement();
            //4.通过根标签来获取 user 标签
            List<Element> elements = rootElement.elements("emp");

            //5.遍历集合,得到每一个 user 标签
            for (Element element : elements) {
                //获取 name 属性
                String name = element.element("name").getText();
                //获取 age 属性
                String age = element.element("age").getText();
                //获取 image 属性
                String image = element.element("image").getText();
                //获取 gender 属性
                String gender = element.element("gender").getText();
                //获取 job 属性
                String job = element.element("job").getText();

                //组装数据
                Constructor<T> constructor = targetClass.getDeclaredConstructor(String.class, Integer.class, String.class, String.class, String.class);
                constructor.setAccessible(true);
                T object = constructor.newInstance(name, Integer.parseInt(age), image, gender, job);

                list.add(object);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

}

测试与问题

代码编写完毕,运行引导类,启动服务进行测试了。Postman测试:

在这里插入图片描述

打开浏览器,在浏览器地址栏输入:localhost:8080/emp.html

在这里插入图片描述

上述案例的功能,虽然已经实现,但是解析XML数据,获取数据的代码,处理数据的逻辑的代码,给页面响应的代码全部都堆积在一起了,全部都写在controller方法中了。

在这里插入图片描述

当前程序的这个业务逻辑还是比较简单的,如果业务逻辑再稍微复杂一点,我们会看到Controller方法的代码量就很大了。

当我们要修改操作数据部分的代码,需要改动Controller
当我们要完善逻辑处理部分的代码,需要改动Controller
当我们需要修改数据响应的代码,还是需要改动Controller

这样呢,就会造成我们整个工程代码的复用性比较差,而且代码难以维护。
其实在现在的开发中,有非常成熟的解决思路,那就是分层开发




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值