SpringBoot 项目入门 0x04

阶段性提示

信息

其实技术是次要的,思想最为重要,换句话说,我们可以把复杂的问题拆解开,拆解成简单的问题,一步一步的去实现,这样实现出来之后,我们再去想如何去优化,从而完成一个复杂的任务。
在这里我简单的描述一下我的学习过程,在学习的初期,知识的广度很重要,这样你的视野就会变广,解决问题的思路也会更多,比如说让你设计一个教务系统(这也是我在大学时期的一个设想以及实现),那么怎么考虑呢?

  1. 首先你得了解教务系统的业务,不知道你要做的东西是干什么的,即使你能力再强也没有用武之地,技术是服务于业务的。
  2. 选择你需要的技术,是CS架构还是BS架构?(当你知识达到一定广度之后,你会知道哪些语言适合做CS架构)BS架构是不是要求跨平台?CS架构的话,要使用哪些技术?
  3. 比如说CS架构,那么前后端使用那些语言,用户量和并发量有多少?是否需要集群?数据库使用Oracle还是MySQL还是SQL-Server?
  4. 如果用户量大的话是否需要缓存?是否需要消息服务器,是否需要静态化页面?

其实要想以软件工程的角度来开发一款软件是一件非常复杂的事情,各位学习的朋友啊,任重而道远,阶段性提示说了好多,就先到这儿,接下来我们聊技术。

规范返回值(VO)

当我们调用一个接口,我们会返回给前端一些数据,但是当我们的服务器如果出现了一些可以捕获的问题时(就是我们可以try-catch的问题),我们不希望返回500,当我们产生正确的结果时,我们希望前端可以知道,这个结果是正常的,服务器状态也是正常的,此时VO的价值就出现了,那么什么是VO呢?

VO: View Object 视图对象

VO和我们之前的pojo很像,只不过我们把结果封装到了VO中,这样就实现了,VO的作用在上面我们也说过了,在这里我先给大家展示一下VO封装之后的返回值。

{
    "code": 200,
    "msg": "success",
    "data": {
        "userList": [
            {
                "name": "zhangsan",
                "status": 0,
                "id": 1,
                "phone": "18808881888"
            },
            {
                "name": "lisi",
                "status": 0,
                "id": 2,
                "phone": "18808881889"
            }
        ]
    }
}

创建vo对象

创建一个vo的包,在这个包中创建一个resultObject的类

image.png

package wuu.shop.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResultObject<T> {
    private int code;
    private String msg;
    private T data;

    public static ResultObject<Object> success(Object data) {
        ResultObject<Object> resultObject = new ResultObject<Object>();
        resultObject.msg = "SUCCESS";
        resultObject.code = 200;
        resultObject.data = data;
        return resultObject;
    }

    public static ResultObject failure() {
        ResultObject<Object> resultObject = new ResultObject<Object>();
        resultObject.msg = "ERROR!";
        resultObject.code = 500;
        return resultObject;
    }

    public static ResultObject<Object> failure(String message) { 
        ResultObject<Object> resultObject = new ResultObject<Object>();
        resultObject.msg = message;
        resultObject.code = 500;
        return resultObject;
    }
}

为什么存在success和failure静态方法呢?在这里我们稳固一下静态方法的作用?

答案

对于我们创建的类,比如public class myClass{},在这个myClass类中,如果存在一些方法,比如get和set方法,我们想要调用这些方法,我们就必须new出来这个对象,才能调用里面的方法,而静态方法,在我们没有创建这个类的时候,可以通过这个类直接调用里面的方法,比如,myClass点(.)那个方法。
正如上面的ResultObject,你要想调用其中的get和set方法,我们就必须先new出来这个ResultObject,然后通过new出来的这个对象,点(.),resultObject.getCode() 注意resultObject是ResultObject new出来的对象,而想用success方法,我们可以直接使用ResultObject.success()注意ResultObject是ResultObject的类

创建使用VO的controller

package wuu.shop.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import wuu.shop.pojo.User;
import wuu.shop.service.UserService;
import wuu.shop.vo.ResultObject;

@RestController
public class VOController {
    @Autowired
    private UserService userService; // 为了配合demo引入了这个

    @GetMapping("/demo1")
    public ResultObject demo1() {
        return ResultObject.success("Hello World");  // 这个是调用成功,返回的结果部分是"Hello World"
    }

    @GetMapping("/demo2")
    public ResultObject demo2() {
        return ResultObject.failure("出错啦");// 这个是调用失败,返回的消息部分是"出错啦"
    }

    @GetMapping("/demo3")
    public ResultObject demo3() {
        return ResultObject.failure(); // 这个是调用失败, 调用的是failure的一个重载方法,没有参数的,所以是ERROR!
    }
    @GetMapping("/demo4")
    public ResultObject demo4(String username) {
        return ResultObject.success(userService.getUserByUserName(username)); // 这个是调用的成功,返回结果是User对象
    }
}

接下来我们看一下这4个demo的调用结果
demo1
demo2
demo3
demo4

对于PostMan发起请求的一些问题

我们在UserController中写两个接口

@RequestMapping(value = "/test", method = RequestMethod.POST)
    public User test(@RequestBody User user) {
        return user;
    }

    @RequestMapping(value = "/test2", method = RequestMethod.POST)
    public User test2(User user) {
        return user;
    }

使用不同方式调用接口

上面的两个接口除了方法名不同,还有一处不同时test使用了@RequestBody,而test2就没有,用到这个,此时我们使用postman进行接口的调用。
我们使用raw的方式提交这个请求,请求参数我们写成JSON

image.png
通过wireshark抓包,发现请求的类型是JSON,并且上图中的结果也是我们期望的结果。
image.png
此时,如果我们使用form-data形式提交呢?
image.png
通过wireshark抓包,发现请求的类型是multipart/form-data,并且存在分隔符,这时候,使用@RequestBody注解的接口就无法解析这个参数了。
image.png

此时,我们调用test2接口,也就是没有@RequestBody注解的那个接口
使用form-data形式提交的请求,发现是可以正常处理的
image.png
但是如果我们使用raw方式提交呢?
发现并没有报错,但是获取不到任何数据。
image.png

原因是什么呢?
原因就是通过上面wireshark抓包获取到的信息,这两种形式的请求体不同,参数部分不一样,@RequestBody只认raw形式的,form-data的会报错,而不加这个注解的,可以解析form-data,而无法解析raw。

form-data 和 raw 的区别

form-data: 可以提交文字和文件
x-www-form-urlencoded: 只能提交键值对
raw: 提交的是json字符串

评论 0

还没有评论,来说点什么吧。

提交后需要审核才会公开。