Spring Boot Web 開發@Controller @RestController 使用教程


在 Spring Boot 中,@Controller 注解是專門用於處理 Http 請求處理的,是以 MVC 為核心的設計思想的控制層。@RestController 則是 @Controller 的衍生注解。

本項目源碼下載

1 Spring Boot Controller

1.1 原理

Spring Boot 本身就 Spring MVC 的簡化版本。是在 Spring MVC 的基礎上實現了自動配置,簡化了開發人員開發過程。

Spring MVC 是通過一個叫 DispatcherServlet 前端控制器的來攔截請求的。而在 Spring Boot 中 使用自動配置把 DispatcherServlet 前端控制器自動配置到框架中。

例如,我們來解析 /users 這個請求

/users請求流程

  1. DispatcherServlet 前端控制器攔截請求 /users
  2. servlet 決定使用哪個 handler 處理
  3. Spring 檢測哪個控制器匹配 /users,Spring 從 @RquestMapping 中查找出需要的信息
  4. Spring 找到正確的 Controller 方法后,開始執行 Controller 方法
  5. 返回 users 對象列表
  6. 根據與客戶端交互需要返回 Json 或者 Xml 格式

1.2 相關注解

在 Spring Boot 中使用到 @Controller 及相關的注解如下,主要分為三個層面進行,請求前,處理中,返回。

應用場景 注解 注解說明
處理請求 @Controller 處理 Http 請求
處理請求 @RestController @Controller 的衍生注解
路由請求 @RequestMapping 路由請求 可以設置各種操作方法
路由請求 @GetMapping GET 方法的路由
路由請求 @PostMapping POST 方法的路由
路由請求 @PutMapping PUT 方法的路由
路由請求 @DeleteMapping DELETE 方法的路由
請求參數 @PathVariable 處理請求 url 路徑中的參數 /user/{id}
請求參數 @RequestParam 處理問號后面的參數
請求參數 @RequestBody 請求參數以json格式提交
返回參數 @ResponseBody 返回 json 格式

注意以上注解需要強調的是 @RestController 是 @Controller 的子集。

@GetMapping、@PostMapping、@PutMapping、@DeleteMapping 是 @RequestMapping 的子集。所以實際上我們只需要掌握 @Controller 和 @RequestMapping 就可以了。

1.3 @Controller 與 @RestController 區別

@Controller 包括了 @RestController。@RestController 是 Spring4 后新加的注解,從 RestController 類源碼可以看出 @RestController 是 @Controller 和 @ResponseBody 兩個注解的結合體。

@Controller=@RestController+@ResponseBody
如下 @RestController 的源碼可以看出他們的關系

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

1.4 @Controller 與 @RestController應用場景

  • @Controller 一般應用在有返回界面的應用場景下.

    例如,管理后台使用了 thymeleaf 作為模板開發,需要從后台直接返回 Model 對象到前台,那么這時候就需要使用 @Controller 來注解。

  • @RestController 如果只是接口,那么就用 RestController 來注解.

    例如前端頁面全部使用了 Html、Jquery來開發,通過 Ajax 請求服務端接口,那么接口就使用 @RestController 統一注解。

1.5 @RequestMapping 說明

首先我們來看看 @RequestMapping 的源碼,我在上面加了注釋

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String name() default "";

    //指定請求的實際地址
    @AliasFor("path")
    String[] value() default {};
    @AliasFor("value")
    String[] path() default {};
    //指定請求的method類型, GET、POST、PUT、DELETE等
    RequestMethod[] method() default {};
    //指定request中必須包含某些參數值是,才讓該方法處理。
    String[] params() default {};
    //指定request中必須包含某些指定的header值,才能讓該方法處理請求。
    String[] headers() default {};
    //指定處理請求的提交內容類型(Content-Type),例如application/json, text/html;
    String[] consumes() default {};
    //指定返回的內容類型,僅當request請求頭中的(Accept)類型中包含該指定類型才返回;
    String[] produces() default {};
}

示例說明:

示例 說明
@RequestMapping("/index") 默認為 GET 方法的路由 /index
@RequestMapping(value="/index",method = RequestMethod.GET) 同上面一條
@RequestMapping(value="/add",method = RequestMethod.POST) 路由為 /add 的 POST 請求
@RequestMapping(value="/add",method = RequestMethod.POST),consumes="application/json" 路由為 /add 的 POST 請求,但僅僅處理 application/json 的請求
@RequestMapping(value="/add",method = RequestMethod.POST),produces="application/json" 路由為 /add 的 POST 請求,強調返回為 JSON 格式
@RequestMapping(value="/add",method = RequestMethod.POST),params="myParam=xyz" 路由為 /add 的 POST 請求,但僅僅處理頭部包括 myParam=xyz 的請求
@RequestMapping(value="/add",method = RequestMethod.POST),headers="Referer=http://www.xyz.com/" 路由為 /add 的 POST 請求,但僅僅處理 來源為 www.xyz.com 的請求

2 @Controller 和 @RestController 示例

本章節,將對兩個注解配合其他注解編寫一系列示例,為了演示 @Controller 返回對應頁面功能,我們在示例中引入了 thymeleaf 模板。具體在 pom.xml 中有說明。

編號 路由 Http方法 方法說明
1 /user/index GET 獲取用戶列表並返回列表頁面
1 /user/add GET 用戶新增頁面
1 /user/save POST 新增用戶的api
1 /user/edit GET 用戶編輯的頁面
1 /user/update POST 編輯用戶的api
1 /user/del GET 刪除用戶頁面
1 /user/deleted POST 刪除用戶頁面的api

2.1 新建 Spring Boot 項目

  1. File > New > Project,如下圖選擇 Spring Initializr 然后點擊 【Next】下一步
  2. 填寫 GroupId(包名)、Artifact(項目名) 即可。點擊 下一步
    groupId=com.fishpro
    artifactId=restcontroller
  3. 選擇依賴 Spring Web Starter 前面打鈎,在模板列中勾選 thymeleaf
  4. 項目名設置為 spring-boot-study-restcontroller.

2.2 依賴 Pom.xml 配置

本項目引入了 web 和 thymeleaf ,具體一人如下代碼:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

並把配置文件重命名為 application.yml ,修改默認測試端口

server:
  port: 8087

2.3 基於 @Controller 的示例代碼

本代碼實例中新增了如下頁面,注意 templates 表示 /resources/tempalates/controller 表示 com.fishpro.restcontroller.controller 包。

  • controller/UserController.java 控制層-用戶類
  • domain/UserDO.java 用戶控實體類
  • templates/user/index.html 視圖-用戶列表頁面
  • templates/user/add.html 視圖-新增用戶頁面
  • templates/user/edit.html 視圖-編輯用戶頁面

2.3.1 返回用戶列表信息 /user/index

本項目源碼下載

首先構件一個虛擬的用戶數據

  /**
     * 模擬一組數據
     * */
    private List<UserDO> getData(){
        List<UserDO> list=new ArrayList<>();

        UserDO userDO=new UserDO();
        userDO.setUserId(1);
        userDO.setUserName("admin");
        list.add(userDO);

        userDO=new UserDO();
        userDO.setUserId(2);
        userDO.setUserName("heike");
        list.add(userDO);

        userDO=new UserDO();
        userDO.setUserId(3);
        userDO.setUserName("tom");
        list.add(userDO);

        userDO=new UserDO();
        userDO.setUserId(4);
        userDO.setUserName("mac");
        list.add(userDO);

        return  list;
    }

1 創建一個用戶列表頁面 /user/index

UserController 增加方法如下圖所示,使用 @RequestMapping 注解,注意 @RequestMapping(method = RequestMethod.GET,value = "/index") 等於 @RequestMapping(value = "/index") 也等於 @RequestMapping("/index") 也等於 @GetMapping("/index")

 /**
     * GET  返回用戶列表信息
     * */
    @RequestMapping(method = RequestMethod.GET,value = "/index")
    public String index(Model model){
        List<UserDO> list =getData();
        model.addAttribute("list",list);//返回 用戶 list
        return "user/index";
    }

    

2 創建 templates/index.html 對應上面的路由 /user/index

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="title">

</div>
<div th:each="user :${list}">
    用戶ID:<span th:text="${user.userId}"></span>
    用戶名:<span th:text="${user.userName}"></span>
</div>
</body>
</html>

3 在瀏覽器中查看

右鍵 RestControllerApplication > Run 在瀏覽器輸入 http://localhost:8087/user/index

用戶ID:1 用戶名:admin
用戶ID:2 用戶名:heike
用戶ID:3 用戶名:tom
用戶ID:4 用戶名:mac

2.3.3 新增用戶頁面 /user/add

本項目源碼下載

在 UserController 中增加 add 路由 /user/add

UserController 增加方法如下圖所示,使用 @RequestMapping 注解,並創建了兩個路由

  • /user/add 對應前端頁面
  • /user/save 對應前端頁面提交按鈕的接口
 /**
     * GET 返回add頁面
     * @GetMapping("/add") = @RequestMapping(method = RequestMethod.GET,value = "/add")
     * */
    @GetMapping("/add")
    public String add(){
        return "user/add";
    }
    /**
     * POST 新增用戶api
     * @return 返回 map對象
     * */
    @RequestMapping(method = RequestMethod.POST,value = "/save")
    @ResponseBody
    public Object save(UserDO user){
        List<UserDO> list= getData();
        list.add(user);//模擬向列表中增加數據
        Map<String,Object> map=new HashMap<>();
        if(null==user){

            map.put("status",3);
            map.put("message","沒有傳任何對象");
            return  map;
        }
        map.put("status",0);
        map.put("data",user);
        return  map;
    }

創建 templates/add.htm 文件對應路由 /user/add

在對應的 templates/add.html中增加代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用戶新增頁面</title>
    <script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.js"></script>
</head>
<body>
<form id="form1">
    <div> <input name="userId" id="userId"  placeholder="請輸入userid"></div>
    <div> <input name="userName" id="userName"   placeholder="請輸入username"></div>
    <div> <input  type="button" value="新增" id="btnSave"/></div>
</form>
<script>
    $(function () {

        $("#btnSave").click(function () {
            $.ajax({
                cache: true,
                type: "POST",
                url: "/user/save",
                data:$('#form1').serialize(),
                dataType:"json",
                async: false,
                error: function (request) {
                    console.log("Connection error");
                },
                success: function (data) {
                    if (data.code == 0) {
                        console.log("成功");
                    } else {
                        console.log("失敗");
                    }

                }
            });
        });

    });
</script>
</body>
</html>

在瀏覽器中測試效果
右鍵 RestControllerApplication > Run 在瀏覽器輸入 http://localhost:8087/user/add

2.3.3 編輯用戶頁面 /user/edit

這部分代碼原理同 2.3.2 代碼原理 通過構件一個編輯頁面,點擊編輯頁面的【保存】提交到后端的 api 中。

本示例中創建了2個接口 1個文件

  • /user/edit 對應前端頁面
  • /user/update 對應前端頁面提交按鈕的接口
  • /templates/user/edit.html
 /**
     * GET 返回編輯頁面
     * @GetMapping("/edit/{id}") = @RequestMapping(method = RequestMethod.GET,value = "/edit/{id}")
     * @PathVariable("id") 表示路由中的動態參數部分
     * @param  id 表示要編輯的用戶id
     * @param model 表示將要輸出到頁面的 Model 對象
     * @return 返回到 user/edit頁面
     * */
    @GetMapping("/edit/{id}")
    public String edit(@PathVariable("id") String id, Model model){
        UserDO user =new UserDO();
        user.setUserId(3);
        user.setUserName("fishpro");
        model.addAttribute("user",user);
        return "user/edit";
    }

    /**
     * POST 修改用戶api
     * @RequestBody 表示參數使用 json 對象傳輸
     * @return 返回 map對象
     * */
    @PostMapping("/update")
    @ResponseBody
    public Object update(@RequestBody UserDO user){
        Map<String,Object> map=new HashMap<>();
        if(null==user){

            map.put("status",3);
            map.put("message","沒有傳任何對象");
            return  map;
        }
        //更新邏輯
        map.put("status",0);
        return  map;
    }

edit.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用戶編輯頁面</title>
    <script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.js"></script>
</head>
<body>
<form id="form1">
    <div> <input name="userId" id="userId"  placeholder="請輸入userid" th:value=${user.userId}> </div>
    <div> <input name="userName" id="userName"   placeholder="請輸入username" th:value=${user.userName}></div>
    <div> <input  type="button" value="新增" id="btnSave"/></div>
</form>
<script>
    $(function () {

        $("#btnSave").click(function () {
            $.ajax({
                cache: true,
                type: "POST",
                url: "/user/update",
                data:$('#form1').serialize(),
                dataType:"json",
                async: false,
                error: function (request) {
                    console.log("Connection error");
                },
                success: function (data) {
                    if (data.code == 0) {
                        console.log("成功");
                    } else {
                        console.log("失敗");
                    }
                }
            });
        });

    });
</script>
</body>
</html>

本項目源碼下載

2.3.3 刪除用戶 /user/delete

本項目源碼下載

/**
     * POST 修改用戶api 
     * @return 返回 map對象
     * */
    @PostMapping("/delete/{id}")
    @ResponseBody
    public Object delete(@PathVariable("id") Integer id){
        List<UserDO> list= getData();
        UserDO userDO=null;
        for (UserDO user:list
                ) {
            if(id.equals(user.getUserId().toString())){
                //刪除用戶
                userDO=user;
                break;
            }
        }

        Map<String,Object> map=new HashMap<>();
        map.put("status",0);
        map.put("data",userDO);
        return  map;
    }

2.4 基於 @RestController 的示例代碼

本章節中是基於 2.3版本中的接口,其實是一樣的功能,詳細見下面的代碼,為了完成代碼功能示例,我們新建了 UserRestController.java,不同的是 我們給類加了 @RestController 修飾符。

@RestController
@RequestMapping("user2")
public class UserRestController {
    //從 UserController 搬過來代碼即可
}

本項目源碼下載


關聯閱讀:

Spring Boot Thymeleaf 模板引擎的使用

Spring Boot RESTful api

Spring Boot Log 日志使用教程

Spring Boot 全局異常處理


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM