從零開始 SpringBoot Web

搭建一個(gè) Spring Boot 應(yīng)用

這不是一個(gè)玩具,用以下方法建的 Spring Boot 應(yīng)用是可以直接在工業(yè)應(yīng)用中的使用的谱净。我們需要以下三個(gè)文件擅威,在 Spring Boot getting started 找就可以了郊丛。

  • pom.xml
  • src/main/java/com/example/springboot/Application.java
  • src/main/java/com/example/springboot/HelloController.java

獲取 HTTP 請求

  1. 從HTTP請求中提取 query string
    查詢參數(shù)一般有如下格式: interface?param1=value1&param2=value2。
    使用 @RequestParam 進(jìn)行接受导盅。@RequestParam 注解 require 參數(shù)默認(rèn)為true揍瑟,表示這個(gè)查詢參數(shù)一定要存在绢片,我們可以設(shè)置為 false恩急,這個(gè)查詢參數(shù)就可以不存在纪蜒。
@RestController
public class HelloController {
    @RequestMapping("/search")
    public String search(@RequestParam("q") String param,
                         @RequestParam(value = "charset", required = false) String charset) {
        return "you are searching" + param + charset;
    }
}
  1. 獲取路徑信息
    @RequestMapping 可以放在 METHOD 或者 TYPE 上面此叠,放在 TYPE 上灭袁,一般表示以此為根目錄。
    我們使用 @PathVariable 來匹配路徑倦炒。
    @DeleteMapping("...") 可以替換成 @RequestMapping(value = "...", method = RequestMethod.DELETE)软瞎。
    此時(shí)我們用 postman 模擬 DELTE 操作涤浇,訪問接口 localhost:8080/repos/golang/lazyben/123。
@RestController
@RequestMapping("repos")
public class IssueController {
    @DeleteMapping("/{owner}/{repo}/{issueNumber}")
    public void unlock(@PathVariable("owner") String owner,
                       @PathVariable("repo") String repo,
                       @PathVariable("issueNumber") String issueNumber) {
        System.out.println(owner);
        System.out.println(repo);
        System.out.println(issueNumber);
    }
}
  1. 從 POST 的負(fù)載中獲取數(shù)據(jù)
    使用 @RequestBody 獲取負(fù)載的內(nèi)容著恩。我們接受的類只要符合 JavaBean 約定就可以了喉誊,Spring 會自動將拿到的 client 傳來的數(shù)據(jù)并生成我們需要類的實(shí)例纵顾。
@RestController
@RequestMapping("repos")
public class IssueController {
    @PostMapping("/{owner}/{repo}/issues")
    public void create(@PathVariable("owner") String owner,
                       @PathVariable("repo") String repo,
                       @RequestBody User obj) {
        System.out.println(obj);
    }
}
public class User {
    private String name;
    private int age;

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

我們用 postman 模擬 POST 請求片挂,發(fā)送了一段 JSON 信息。

{
    "name": "lazyben",
    "age": 23
}

得到了錯(cuò)誤415沪饺,如下所示整葡。這里犯了一個(gè)小錯(cuò)誤讥脐,也是很容易出錯(cuò)的地方啼器。這是由于 client 在向 server 發(fā)的 request 中的 header 沒有指明 Media Type端壳。解決辦法很簡單枪蘑,只需要聲明 Content-Type:application/json 即可岳颇。

{
    "timestamp": "2021-01-05T10:31:29.406+00:00",
    "status": 415,
    "error": "Unsupported Media Type",
    "message": "",
    "path": "/repos/golang/lazyben/issues"
}

對于比較少的數(shù)據(jù),我們可以直接用表單來傳栗精,此時(shí) Content-Type:application/x-wwwform-urlencoded 瞻鹏,并使用 @RequestParam新博。Spring 只需要提取 body 中的參數(shù)即可,下面是一個(gè)例子:

@RestController
@RequestMapping("repos")
public class IssueController {
    @PostMapping("/login")
    public void login(@RequestParam("username") String username,
                      @RequestParam("password") String password) {
        System.out.println(username);
        System.out.println(password);
    }
}

最后我們對從POST請求中獲取參數(shù)做一個(gè)總結(jié)寥殖。

場景 Content-Type 使?注解 適?于
提取整個(gè)body中的對象 application/json @RequestBody JSON
提取body中的參數(shù) application/x-wwwform-urlencoded @RequestParam 表單

生成 HTTP 響應(yīng)

  1. 直接操作 HttpServletRespnse 對象
    一個(gè) WebApp 監(jiān)聽80端口嚼贡,從這個(gè)端口進(jìn)來的 HTTP 請求粤策,是怎么變成 Java 對象的呢误窖?在 WebApp 更底層的地方,還存在著 Servlet 容器柔吼。Servlet 容器是 Java 世界處理 Web 應(yīng)用的標(biāo)準(zhǔn)丙唧,它可以從機(jī)器的端口上面讀取字節(jié)流,把它封裝成 Java 對象方便上層進(jìn)行處理溪厘。上層處理完之后牌柄,把結(jié)果丟給 Servlet 容器珊佣,Servlet 容器又可以將其變成字節(jié)流,返回給端口。因此 Servlet 容器扮演的是從字節(jié)流到 Java 對象轉(zhuǎn)換的中間層僻爽。它的核心接口就是 HttpServletRequestHttpServletResponse胸梆。如下代碼所示,為什么我們可以直接寫在參數(shù)里呢兢卵?因?yàn)镾ervlet 容器已經(jīng)幫我們封裝好了 Java 對象秽荤。
@RestController
public class HelloController {
    @RequestMapping("/")
    public String index(HttpServletRequest request, HttpServletResponse response) {
        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
        return "Greetings from Spring Boot!";
    }
}

可以看見的是柠横,我們成功顯示了 Greetings from Spring Boot! 牍氛,但也拿到了 error 400。


我們來看一下HttpServletRequestHttpServletResponse這兩個(gè)對象到底是什么紊扬。他們兩個(gè)代表了當(dāng)前正在進(jìn)行的 HTTP 請求和 HTTP 響應(yīng)餐屎。打上斷點(diǎn)玩祟,來看一看里面有些什么。request 中有 header庆聘,cookies等伙判。我們可以用 response.getWriter.write("...") 直接寫一些東西回去±漳В總的來說這個(gè)方式比較偏向底層冠绢、原始常潮、簡單喊式、粗暴。

  1. 直接返回HTML字符串
@RestController
public class HelloController {
    @RequestMapping("/")
    public String index() {
        return "<h1>hello word!</h1>";
    }
}
  1. 返回對象,并自動格式化成JSON
    這是一個(gè)比較常用的方式献联。對應(yīng)的我們要寫上 @ResponseBody
@RestController
public class HelloController {
    @RequestMapping("/")
    @ResponseBody
    public Object index() {
        Map<String, Object> result = new HashMap<>();
        result.put("result", Arrays.asList("aaa", "bbb", "ccc"));
        return result;
    }
}

下面是我們得到的結(jié)果里逆,可以發(fā)現(xiàn)它被自動格式化為了JSON格式。

{"result":["aaa","bbb","ccc"]}
  1. 模版引擎渲染
    常用的模版引擎有JSP/Velocity/Freemaker龄减。

RESTful API

  1. 使?HTTP動詞來代表動作
  • GET:獲取資源
  • POST:新建資源
  • PUT:更新資源
  • DELTE:刪除資源
  1. 使?URL(名詞)來代表資源
  • 資源??沒有動詞
  • 使?復(fù)數(shù)來代表資源列表

github api 設(shè)計(jì)是業(yè)界的標(biāo)桿

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末希停,一起剝皮案震驚了整個(gè)濱河市宠能,隨后出現(xiàn)的幾起案子磁餐,更是在濱河造成了極大的恐慌,老刑警劉巖羞延,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伴箩,死亡現(xiàn)場離奇詭異嗤谚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)旁赊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來椅野,“玉大人终畅,你說我怎么就攤上這事■伲” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵芒炼,是天一觀的道長瘫怜。 經(jīng)常有香客問我,道長本刽,這世上最難降的妖魔是什么鲸湃? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮暗挑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘斜友。我一直安慰自己炸裆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布鲜屏。 她就那樣靜靜地躺著烹看,像睡著了一般。 火紅的嫁衣襯著肌膚如雪洛史。 梳的紋絲不亂的頭發(fā)上惯殊,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機(jī)與錄音也殖,去河邊找鬼土思。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的己儒。 我是一名探鬼主播崎岂,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼址愿!你這毒婦竟也來了该镣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤响谓,失蹤者是張志新(化名)和其女友劉穎损合,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娘纷,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嫁审,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赖晶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片律适。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖遏插,靈堂內(nèi)的尸體忽然破棺而出捂贿,到底是詐尸還是另有隱情,我是刑警寧澤胳嘲,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布厂僧,位于F島的核電站,受9級特大地震影響了牛,放射性物質(zhì)發(fā)生泄漏颜屠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一鹰祸、第九天 我趴在偏房一處隱蔽的房頂上張望甫窟。 院中可真熱鬧,春花似錦蛙婴、人聲如沸粗井。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽背传。三九已至,卻和暖如春台夺,著一層夾襖步出監(jiān)牢的瞬間径玖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工颤介, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留梳星,地道東北人赞赖。 一個(gè)月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像冤灾,于是被迫代替她去往敵國和親前域。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容