返回随笔Java全栈
完成ENGINEERING NOTE

SpringBoot

从 SpringBoot Web 项目结构和 Controller 入门,整理 HTTP 请求响应、参数处理与基础接口开发。

后端SpringBoot

SpringBootWeb入门

在以模板创建一个SpringBoot项目后,发现其src文件夹下已经有了main和test文件夹,且main文件夹中包含了入口文件。新建一个文件HelloController,此文件中包括了浏览器请求时返回的函数。 HelloController.java:

//这一行注解表示这个类是一个请求处理类
@RestController
public class HelloController {
    //这个注解表示这个函数是一个请求处理函数,且处理的是hello请求
    @RequestMapping("/hello")
    public String hello() {
        System.out.println("hello world");
        return "Hello World";
    }
}

点击运行,打开浏览器并输入localhost:8080/hello,即可看到HelloWorld消息。

HTTP协议

请求数据格式

http请求的数据格式分为get和post请求,get请求的请求内容位于请求行内,有大小限制,但post位于请求体内,没有大小限制。

GET /hello HTTP/1.1               请求行
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: Pycharm-962094d3=ae3baddc-2a20-4216-b8fa-e74dc567bffd
Host: localhost:8080
以上都是请求头

如果是post还有下面的请求体:
{ "status":1,"name":"KringKoter"}

请求响应格式

请求响应的数据也分为post和get,这与上面一致。

HTTP/1.1 200                             响应行/1.1:协议版本,200:返回代码
Content-Type: text/html;charset=UTF-8    响应头,形式是key:value
Content-Length: 38
Date: Tue, 26 Sep 2023 06:10:36 GMT
Keep-Alive: timeout=60
Connection: keep-alive

如果是post,下面还有响应体
  • 返回代码为以下形式:
**代码** **状态信息**
1xx 响应中-临时响应码,表示请求已经接收,告诉客户端应该继续请求,如果完成,则忽略
2xx 成功
3xx 重定向-重定向到其他地方,让客户端再发起一次请求完成整个过程
4xx 客户端错误-处理发生错误,责任在客户端
5xx 服务器错误-处理发生错误,则仍在服务端
- 常用的返回码:
**状态码** **英文描述** **解释**
200(! OK 处理成功
302 Found 表示所请求的资源已经移动到另一个url,浏览器会自动访问这个页面
304 Not Modified 告诉客户端服务器的内容自上次请求后没变,直接用本地缓存即可
400 Bad Request 客户端有语法错误,服务器无法理解
404(! Not Found 请求资源不存在,一般是url输入错误,或者网站资源被删除
403 Forbidden 没有权限
405 Method Not Allowed 请求方式有误,比如get误用了post
428 Precondition Required 服务器要求有条件的请求,必须携带特定的请求头
429 Too Many Requests 给服务器发送了太多的请求
431 Request Header Fields Too Large 请求头太大,服务器不愿意处理请求
500(! Internal Server Error 服务器崩了
503 Service Unavailable 服务器尚未准备好,服务器刚刚启动,还未初始化很好
- 常见的响应头:
**字段** **信息**
Content-Type 表示响应内容的类型,例如text/html,application/json
Content-Length 表示该响应内容的长度(字节数)
Content-Encoding 表示响应压缩算法,比如gzip
Cache-Control 指示客户端如何缓存,例如max-age=300表示最多缓存300秒
Set-Cookie 告诉浏览器为当前页面所在的区域设置cookie
## **web服务器** web服务器对http协议操作进行封装,简化web开发。且能部署web项目,对外提供网上信息浏览服务。 - Tomcat 这是一个轻量级web开源服务器,支持servlet,jsp等少量java ee规范。也被称为web容器,servlet容器。 ## **Tomcat的基本使用** Tomcat是一个绿色软件,直接解压后,找到bin目录里的start.bat即可运行。若出现乱码,需要到logging配置文件里将UTF-8改为GDK。若启动后无法运行,需要配置环境变量JAVA_HOME至java安装路径。 Tomcat启动后,默认占用端口8080,可以在conf/server.xml中修改端口号。 将带有index.html的文件放在webapps中即可完成部署。 ## **请求参数** ### **请求简单参数** 直接将参数名写在函数的参数列表即可。可以使用@RequestParam注解来指定请求的参数名,require标签指定了是否必须(默认为true) ```plain text @RequestMapping("/simplePojo")    public String simplePojo(@RequestParam(name = "uname", require = false)String username, int id) {        System.out.println(name + ":" + id);        return "OK"; } ``` ### **请求实体参数** 将对象名写在参数列表即可。 ```plain text @RequestMapping("/complexPojo")    public String complexPojo(User user) {        System.out.println(user);        return "OK"; } ``` ### **请求数组/集合参数** 需要用@RequestParam指定参数为List\<\> ```plain text @RequestMapping("/listParam")    public String listParam(@RequestParam List name) {        System.out.println(name);        return "OK"; } ``` ### **请求时间参数** 时间参数将封装在一个LocalDate或LocalDateTime对象中,需要使用@RequestParam(patter="")来指定时间格式,注意请求的参数名必须和变量名一致,另外还需要注意日期标准格式是"yyyy-MM-dd HH\:mm\:ss",M和H需要大写,否则传递参数不识别。 ```plain text @RequestMapping("/time")    public String getTime(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")LocalDateTime localDateTime) {        System.out.println(localDateTime);        return "OK"; } ``` ### **请求json参数** json参数需要封装在一个对象中,这个对象可以自定义。需要在对象前加上@RequestBody注解来声明这个一个json参数。 ```plain text @RequestMapping("/json")    public String getJson(@RequestBody User user) {        System.out.println(user);        return "OK"; } ``` 传递的json内的参量key需要与对象中的属性名相同,例如: ```plain text {    "name":"JSKringkoter",    "id":3,    "address":{        "city":"EHIS",        "street":"EHIS-4"   } } ``` ```plain text public class Address {    public String city;    public String street; }

public class User {    public String name;    public int id;    public Address address; }

### **路径参数**
可以在@RequestMapping的路径中使用\{id\}来动态获取路径参数。在函数的参量中,使用@PathVariable来指定后面的参量是一个路径参数。
```plain text
@RequestMapping("/path/{id}")
    public String pathParam(@PathVariable Integer id) {
        System.out.println(id);
        return "OK";
    }
}

也可以指定多个参数。

@RequestMapping("/{name}/{id}")
    public String pathParam(@PathVariable String name, @PathVariable Integer id) {
        System.out.println(name + ":" + id);
        return "OK";
    }
}

统一响应结果

可以使用一个Result来统一响应结果。Result类可以使用静态方法来简化创建流程,其包含了一个无参构造函数,一个有参构造函数,两个success工厂函数,一个error工厂函数。Result类中code数据表明了传递信息的id,message表示信息,data则是响应的数据。大致定义如下:

public class Result {
    private Integer code;
    private String message;
    private Object data;

    public Result() {
    }

    public Result(int code, String message, Object data) {
        this.code = code;
        this.message = message;
        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() {
        return new Result(0, "error", null);
    }
    public int getCode() {
        return code;
    }

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

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return data;
    }

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

    @Override
    public String toString() {
        return "Result{" +
                "code=" + code +
                ", message='" + message + '\'' +
                ", data=" + data +
                '}';
    }
}

对应的响应方法如下:

@RequestMapping("/ello")
    public Result hello() {
        return new Result(1, "helloworld", null);
}

 @RequestMapping("/result")
    public Result getResult() {
        Address addr = new Address();
        addr.setCity("EHIS");
        addr.setStreet("EHIS-4");

        return Result.success(addr);
}

@RestController

@RestController是@Controller、@ResponseBody的组合体。@ResonseBody可以作用在@Controller类或者方法上,作用是直接将方法的返回值作为响应参数