这是Spring Boot的第二篇笔记,上一篇记录了如何安装软件并简单实现Hello World。之前说过,自己关于动态网站只学过JSP,涉猎过Django/Flask,因此不是很习惯网上Spring Boot教程,于是有了这个系列。按照习惯,一般都是在动态项目里实现静态页面展示、接着实现处理Requests及返回Response,因此本文分为两个部分。

静态文件部分

静态文件可以存放在resources文件夹下的resources、static、public文件夹下,可以自行建立以下名字的文件夹。

我是如何知道静态文件存放规则的呢?

可以从org.springframework.boot.autoconfigure.web包中的ResourceProperties.java中看到关于静态文件位置的代码。当然我觉也可以在src>resources下的application.properties文件里面改这个,但没必要。

@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {

	private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
			"classpath:/resources/", "classpath:/static/", "classpath:/public/" };

	/**
	 * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
	 * /resources/, /static/, /public/].
	 */
    private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;

实现

在public下新建一张名为login的HTML文件,展示一张简单的登录页面,代码如下。

<!DOCTYPE html>
<html lang="en">
    <head>
            <meta charset="UTF-8">
            <title>Title</title>
    </head>
    <body>
            <form>
                <input type="text" name="email">
                <input type="password" name="pswd">
                <button type="submit"> 提交</button>
            </form>
    </body>
</html>

启动程序,访问localhost:8080/login.html,成功看到奇丑无比的页面。

处理动态请求

之前JSP的方法是java写Servlet、前端使用Ajax,实现前后端分离。

在spring里有三种方式可以接受请求

  1. @PathVariable
  2. @RequestParam
  3. @RequestBody

@PathVariable

[1]https://book.douban.com/subject/30302069

[2]https://book.douban.com/subject/3616310

[3]https://www.douban.com/people/sunmker

[4]https://www.douban.com/people/ahbei

12是豆瓣书籍页面,34为豆瓣用户资料页面。

这两组URL都是要规律的,即变化的是最后部分,这个时候使用@PathVariable注解比较合适

@RequestMapping("/subject/{id}")
//获取书号
public viod getById(@PathVariable int id){
    ……
}

@RequestMapping("/people/{name}")
//获取书号
public viod getByName(@PathVariable String name){
    ……
}

@RequestParam

@RequestParam和@RequestBody都可以获取请求,但是两者对于请求的Content-Type要求不一样。

Content-Type
@RequestParam application/x-www-form-urlencoded
@RequestBody application/json

提交请求有常用get/post两种方式,@RequestParam都可以获取,不管是get方法显示在URL中还是post隐藏在requests中。

因此,所以不要单纯以为@RequestParam只能获取下面这种方式的参数,POST也是可以的。

https://book.douban.com/people/sunmker/collect?start=30&sort=time&rating=all&filter=all&mode=grid

这串url是我的豆瓣「已读」的第三页,可以看到一连串的键值对,如起始值=30、排序方式为时间顺序等,使用RequestParam来读取键值对

@RequestMapping("/collect")
//获取start、sort参数
//defaultValue设置默认参数,也可以想sort处简写
public void user(@RequestParam(value="start", defaultValue="0") int id,@RequestParam("sort") String name) {
    ……
}

@RequestBody

@RequestBody的好处就是在于可以接受一个json的对象,可以和现有的java类很好的结合在一起,代码为例。

  1. Employee.java(注意,一定要写上get/set方法)

    package cn.sunmker.demo;
    
    class Employee {
    private String email;
    private String pswd;
    Employee(){}
    
    public Employee(String email, String pswd) {
        this.email = email;
        this.pswd = pswd;
    }
    
    public String getEmail() {
        return email;
    }
    
    public void setEmail(String email) {
        this.email = email;
    }
    
    public String getPswd() {
        return pswd;
    }
    
    public void setPswd(String pswd) {
        this.pswd = pswd;
    }
    }
    
    
  2. RR.java

    package cn.sunmker.demo;
    
    import org.springframework.web.bind.annotation.*;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @RestController
    public class RR {
    List<Employee> all = new ArrayList();
    
    {
        all.add(new Employee("1@qq.com", "1"));
        all.add(new Employee("2@qq.com", "2"));
        all.add(new Employee("3@qq.com", "3"));
    }
    
    @GetMapping("/getNum")
    public int getNum() {
        return all.size();
    }
    
    @RequestMapping("/addOne")
    public void addOne(@RequestBody Employee employee) {
        all.add(employee);
    }
    
    @GetMapping("/getId/{id}")
    public Employee getByid(@PathVariable int id){
        return all.get(id);
    }
    
    @RequestMapping("/getAll")
    public List<Employee> getAll() {
        return all;
    }
    }
    
  3. index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8">
    <script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>
    </head>
    <body>
    <form>
    <input type="email" name="email" id="inputEmail"  required autofocus>
    <br>
    <input type="password" name="pswd" id="inputPassword"   required>
    <button type="submit" onclick="ssd();">Sign in</button>
    </form>
    <script>
    function ssd() {
        a = $(inputEmail).val();
        b = $(inputPassword).val();
        console.log(a, b);
        $.ajax(
            {
                type: 'post',
                url: 'addOne',
                data: JSON.stringify({"email": a, "pswd": b}),
                contentType: "application/json",
                dataType: 'JSON',
            }
        )
    }
    </script>
    </body>
    </html>
    

addOne使用了@RequestBody注解,index.html中使用ajax制造application/json的post请求。

可以使用getNum查看数量是否增加。

@RequestBody可以使用Get方法吗?

用ajax不行,postman/httpei可以,网上的例子也都是用POST的,先留个疑惑,往下走。

总结

一般来说,感觉还是@RequestParam,@PathVariable比较常用,@RequestBody看起来比较高级,但是感觉适用场景比较少。

Srping(三) 转发/重定向