AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁 > 科技  > 軟件

如何編寫優(yōu)雅的 Controller 代碼?

來源: 責(zé)編: 時(shí)間:2024-06-24 17:13:27 120觀看
導(dǎo)讀作為一名 Java程序員,對(duì) Controller肯定不陌生,它是與外部客戶端通信的入口,比如常見的 REST 操作(GET、PUT、POST、DELETE等),那么,Controller里面應(yīng)該如何編寫才算優(yōu)雅呢?其實(shí),一個(gè)優(yōu)雅的 Controller,里面的代碼主要包含下面

作為一名 Java程序員,對(duì) Controller肯定不陌生,它是與外部客戶端通信的入口,比如常見的 REST 操作(GET、PUT、POST、DELETE等),那么,Controller里面應(yīng)該如何編寫才算優(yōu)雅呢?37C28資訊網(wǎng)——每日最新資訊28at.com

37C28資訊網(wǎng)——每日最新資訊28at.com

其實(shí),一個(gè)優(yōu)雅的 Controller,里面的代碼主要包含下面 6個(gè)部分:37C28資訊網(wǎng)——每日最新資訊28at.com

  • 接收 HTTP(s)請(qǐng)求
  • 解析請(qǐng)求參數(shù)
  • 驗(yàn)證請(qǐng)求參數(shù)
  • 調(diào)用業(yè)務(wù)方法
  • 組織返回?cái)?shù)據(jù)
  • 統(tǒng)一異常處理

37C28資訊網(wǎng)——每日最新資訊28at.com

下面一一講解這 6個(gè)部分:37C28資訊網(wǎng)——每日最新資訊28at.com

37C28資訊網(wǎng)——每日最新資訊28at.com

一、接收 HTTP(s)請(qǐng)求

接收 HTTP(s)請(qǐng)求是 Controller的入口,這里以查詢用戶信息為例進(jìn)行說明,如下代碼:37C28資訊網(wǎng)——每日最新資訊28at.com

@RestControllerpublic class UserController {    @GetMapping("/user/{userId}")    public void getUserById(@PathVariable String userId) {        // 業(yè)務(wù)邏輯    }}

在上面的示例中,我們使用 URL/user/{id}接收用戶發(fā)出的 GET請(qǐng)求,然后通過getUserById方法進(jìn)行真實(shí)的業(yè)務(wù)處理。通過上面的代碼,一個(gè)請(qǐng)求就被 Controller層成功接收了。37C28資訊網(wǎng)——每日最新資訊28at.com

二、解析請(qǐng)求參數(shù)

接收到請(qǐng)求后,一般需要對(duì)請(qǐng)求參數(shù)進(jìn)行解析,如下示例代碼:37C28資訊網(wǎng)——每日最新資訊28at.com

@RestControllerpublic class UserController {    @PostMapping("/user/register")    public void getGradeById(@RequestBody User user) {        // 代碼邏輯    }}public class User {    private String nickname;    private Integer age;    // getters and setters and constructors}

上述示例代碼將請(qǐng)求的 body映射到 User對(duì)象上,因此,請(qǐng)求的 body體應(yīng)該是:37C28資訊網(wǎng)——每日最新資訊28at.com

{  "nickname": "huahua",  "age": "18"}

在 SpringMVC 中,常見的參數(shù)類型及其用途如下:37C28資訊網(wǎng)——每日最新資訊28at.com

1.原始 HTTP請(qǐng)求和響應(yīng)對(duì)象

直接接收原始的 HTTP請(qǐng)求和響應(yīng)對(duì)象,HttpServletRequest 和 HttpServletResponse37C28資訊網(wǎng)——每日最新資訊28at.com

@RequestMapping("/test")public void example(HttpServletRequest request, HttpServletResponse response) {    // 處理請(qǐng)求和響應(yīng)}

2.路徑變量 (@PathVariable)

用于獲取 URL 路徑中的動(dòng)態(tài)部分。37C28資訊網(wǎng)——每日最新資訊28at.com

@RequestMapping("/user/{id}")public String getUser(@PathVariable("id") String userId) {    // 使用 userId 進(jìn)行處理    return "userDetail";}

3.請(qǐng)求參數(shù) (@RequestParam)

用于獲取 URL 查詢參數(shù)或表單數(shù)據(jù)。37C28資訊網(wǎng)——每日最新資訊28at.com

@RequestMapping("/search")public String search(@RequestParam("query") String query) {    // 使用 query 進(jìn)行搜索    return "searchResults";}

4.請(qǐng)求體 (@RequestBody)

用于接收請(qǐng)求體中的數(shù)據(jù),常用于處理 JSON 或 XML 格式的數(shù)據(jù)。37C28資訊網(wǎng)——每日最新資訊28at.com

@RequestMapping(value = "/create", method = RequestMethod.POST)public String create(@RequestBody User user) {    // 處理 user 對(duì)象    return "user";}

5.模型屬性 (@ModelAttribute)

用于綁定表單數(shù)據(jù)到模型對(duì)象。37C28資訊網(wǎng)——每日最新資訊28at.com

@RequestMapping("/register")public String register(@ModelAttribute User user) {    // 處理 user 對(duì)象    return "user";}

6.會(huì)話屬性 (@SessionAttribute)

用于訪問會(huì)話中的屬性。37C28資訊網(wǎng)——每日最新資訊28at.com

@RequestMapping("/profile")public String profile(@SessionAttribute("user") User user) {    // 處理會(huì)話中的 user 對(duì)象    return "profile";}

7.請(qǐng)求頭 (@RequestHeader)

用于訪問 HTTP 請(qǐng)求頭信息。37C28資訊網(wǎng)——每日最新資訊28at.com

@RequestMapping("/headers")public String headers(@RequestHeader("User-Agent") String userAgent) {    // 使用 userAgent 進(jìn)行處理    return "headerInfo";}

8.Cookie 值 (@CookieValue)

用于訪問 Cookie 的值。37C28資訊網(wǎng)——每日最新資訊28at.com

@RequestMapping("/cookies")public String cookies(@CookieValue("sessionId") String sessionId) {    // 使用 sessionId 進(jìn)行處理    return sessionId;}

9.自定義參數(shù)解析器

可以通過實(shí)現(xiàn) HandlerMethodArgumentResolver接口來自定義參數(shù)解析邏輯。37C28資訊網(wǎng)——每日最新資訊28at.com

@RequestMapping("/custom")public String custom(CustomObject customObject) {// 使用自定義對(duì)象進(jìn)行處理    return "";}

三、驗(yàn)證請(qǐng)求參數(shù)

請(qǐng)求參數(shù)的驗(yàn)證需要在 Controller層完成,如下代碼,對(duì) nickname進(jìn)行判空處理,參數(shù)驗(yàn)證一般有 2種方式:37C28資訊網(wǎng)——每日最新資訊28at.com

  • 原始方式,這種方式比較靈活,如果需要對(duì)參數(shù)進(jìn)行一些邏輯計(jì)算后再校驗(yàn);
  • 借助三方工具,比如 Spring validation,javax validation等,這種方式靈活度會(huì)低一些,但是更優(yōu)雅;
// 原始方式校驗(yàn)參數(shù)@RestControllerpublic class UserController {    @PostMapping("/user/register")    public void getGradeById(@RequestBody User user) {        // 代碼邏輯        if (StringUtils.isBlank(user.getNickname)) {            throw new Exception("Nickname is required.");        }    }}

或者使用 Spring validation驗(yàn)證機(jī)制,Controller需要增加@Validated注解,User對(duì)象中增加@NotBlank注解。37C28資訊網(wǎng)——每日最新資訊28at.com

// 借助Spring validation方式校驗(yàn)參數(shù)@RestControllerpublic class UserController {    @PostMapping("/user/register")    public void getGradeById(@Validated @RequestBody User user) {        // 代碼邏輯    }}public class User {    @NotBlank(message = "Nickname is required.")    private String nickname;    private Integer age;    // getters and setters and constructors}

四、調(diào)用業(yè)務(wù)方法

如下代碼,調(diào)用 UserService.register()進(jìn)行注冊(cè)業(yè)務(wù)處理:37C28資訊網(wǎng)——每日最新資訊28at.com

@RestControllerpublic class UserController {    private final UserService userService;    public UserController(UserService userService) {        this.userService = userService;    }    @PostMapping("/user/register")    public void getGradeById(@Validated @RequestBody User user) {        // 調(diào)用注冊(cè)的業(yè)務(wù)方法        userService.register(user);    }}public class User {    @NotBlank(message = "Nickname is required.")    private String nickname;    private Integer age;    // getters and setters and constructors}

關(guān)于調(diào)用業(yè)務(wù)方法,這里的業(yè)務(wù)方法是寫一個(gè)大而全的方法?還是需要按業(yè)務(wù)歸類?37C28資訊網(wǎng)——每日最新資訊28at.com

遵守一個(gè)原則:有強(qiáng)關(guān)聯(lián)性的邏輯放在一個(gè)service方法內(nèi),沒有強(qiáng)關(guān)聯(lián)性的單令拎出來。37C28資訊網(wǎng)——每日最新資訊28at.com

這里以用戶注冊(cè)之后需要新人發(fā)券為例進(jìn)行說明:37C28資訊網(wǎng)——每日最新資訊28at.com

大而全的方法:37C28資訊網(wǎng)——每日最新資訊28at.com

    @PostMapping("/user/register")    public void getGradeById(@Validated @RequestBody User user) {        // 調(diào)用注冊(cè)的業(yè)務(wù)方法        userService.doRegister(user);    }        public String doRegister(Uswr user){        String userId = userService.register(user);        coupon.sendCoupon(userId);        // 其他業(yè)務(wù)邏輯        return userId;    }

業(yè)務(wù)歸類:37C28資訊網(wǎng)——每日最新資訊28at.com

    @PostMapping("/user/register")    public void getGradeById(@Validated @RequestBody User user) {        // 調(diào)用注冊(cè)的業(yè)務(wù)方法        userService.register(user);        coupon.sendCoupon(userId);    }

五、組織返回?cái)?shù)據(jù)

如下代碼,調(diào)用 UserService.register()進(jìn)行注冊(cè)業(yè)務(wù)處理:37C28資訊網(wǎng)——每日最新資訊28at.com

@RestControllerpublic class UserController {    private final UserService userService;    public UserController(UserService userService) {        this.userService = userService;    }    @PostMapping("/user/register")    public UserResponse getGradeById(@Validated @RequestBody User user) {        // 調(diào)用注冊(cè)的業(yè)務(wù)方法        String userId = userService.regist(user);        return new UserResponse(userId, user.getNickname);    }}public class UserResponse {    private String userId;    private String nickname;    // getters and setters and constructors}

六、統(tǒng)一異常處理

比如上述過程在 userService.regist(user);出現(xiàn)異常時(shí),可以做一個(gè)try-catch,然后在 Controller層封裝有業(yè)務(wù)意思的異常信息:37C28資訊網(wǎng)——每日最新資訊28at.com

@RestControllerpublic class UserController {    private final UserService userService;    @PostMapping("/user/register")    public UserResponse getGradeById(@Validated @RequestBody User user) {        // 調(diào)用注冊(cè)的業(yè)務(wù)方法        try {            String userId = userService.regist(user);        } catch (Exception e) {            throw new CustomException();        }        return new UserResponse(userId, user.getNickname);    }}

建議和總結(jié)

看過很多代碼,業(yè)務(wù)邏輯全部寫在 Controller層,并不能說這樣的做法是錯(cuò)的,但是看起來很別扭,不優(yōu)雅!因此,建議在編寫代碼時(shí),最好能遵守一個(gè)比較好的規(guī)范,比如常見的SOLID規(guī)范。37C28資訊網(wǎng)——每日最新資訊28at.com

SOLID 實(shí)際上是五個(gè)設(shè)計(jì)原則首字母的縮寫,它們分別是:37C28資訊網(wǎng)——每日最新資訊28at.com

  • 單一職責(zé)原則(Single responsibility principle, SRP)
  • 開放封閉原則(Open–closed principle, OCP)
  • Liskov 替換原則(Liskov substitution principle, LSP)
  • 接口隔離原則(Interface segregation principle, ISP)
  • 依賴倒置原則(Dependency inversion principle, DIP)

另外,建議我們技術(shù)人員平時(shí)多去閱讀一些優(yōu)秀開源框架,學(xué)習(xí)他們的設(shè)計(jì)思想,代碼規(guī)范,相信我:養(yǎng)成一個(gè)良好的編碼規(guī)范,絕對(duì)受益頗多!37C28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-96045-0.html如何編寫優(yōu)雅的 Controller 代碼?

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 美國兩名 05 后高中生聯(lián)手打造 API 初創(chuàng),已獲 50 萬美元融資

下一篇: Python 處理 CSV 文件的 12 個(gè)高效技巧

標(biāo)簽:
  • 熱門焦點(diǎn)
Top