Rumah  >  Artikel  >  Java  >  Cara mengendalikan pulangan antara muka bersatu SpringBoot dan pengecualian global

Cara mengendalikan pulangan antara muka bersatu SpringBoot dan pengecualian global

PHPz
PHPzke hadapan
2023-05-12 16:01:061838semak imbas

1. SpringBoot tidak menggunakan format pemulangan bersatu

Secara lalai, SpringBoot akan mempunyai tiga situasi pemulangan berikut.

1.1 Gunakan rentetan untuk mengembalikan

@GetMapping("/getUserName")
public String getUserName(){
    return "HuaGe";
}

Panggil antara muka untuk mengembalikan hasil:

HuaGe

1.2 Gunakan kelas entiti untuk mengembalikan

rreee

Panggil antara muka untuk pulangkan hasil:

@GetMapping("/getUserName")
public User getUserName(){
    return new User("HuaGe",18,"男");
}

1.3 Kembalikan

dalam keadaan tidak normal
{
  "name": "HuaGe",
  "age": "18",
  "性别": "男", 
}

mensimulasikan pengecualian penuding nol Tanpa sebarang pengendalian pengecualian, anda boleh melihat hasil pulangan lalai SpringBoot:

@GetMapping("/getUserName")
public static String getUserName(){
    HashMap hashMap = Maps.newHashMap();
    return hashMap.get(0).toString();
}

Untuk situasi di atas, jika keseluruhan projek tidak mentakrifkan format pemulangan bersatu dan lima pembangun bahagian belakang mentakrifkan lima format pemulangan, ini bukan sahaja akan menjadikan kod mengembang, bahagian hadapan dan belakang -Kecekapan dok hujung akan menjadi rendah, tetapi juga akan terdapat beberapa ketidakkonsistenan Apabila situasi tertentu berlaku, seperti bahagian hadapan secara langsung memaparkan butiran pengecualian, dll., ini memberikan pengguna pengalaman yang sangat buruk.

2. Permainan asas

Perkara yang paling biasa dalam projek ialah merangkum kelas alat Maklumat medan yang perlu dikembalikan ditakrifkan dalam kelas, dan maklumat antara muka yang perlu dikembalikan ke bahagian hadapan dikapsulkan melalui kelas ini, ini boleh menyelesaikan masalah format pulangan yang tidak konsisten.

2.1 Perihalan Parameter

  • kod: kod status, latar belakang boleh mengekalkan set kod status bersatu

  • mesej: maklumat perihalan, maklumat pantas kejayaan/kegagalan panggilan antara muka;

  • 2.2 Penerangan Proses

  • Kelas Keputusan Baharu

    {
        "timestamp": "2021-08-09T06:56:41.524+00:00",
        "status": 500,
        "error": "Internal Server Error",
        "path": "/sysUser/getUserName"
    }
  • Tentukan kembali kod status

    public class Result<T> {
        
        private int code;
        
        private String message;
        
        private T data;
    
        public Result() {}
        public Result(int code, String message) {
            this.code = code;
            this.message = message;
        }
        
        /**
         * 成功
         */
        public static <T> Result<T> success(T data) {
            Result<T> result = new Result<T>();
            result.setCode(ResultMsgEnum.SUCCESS.getCode());
            result.setMessage(ResultMsgEnum.SUCCESS.getMessage());
            result.setData(data);
            return result;
        }
    
        /**
         * 失败
         */
        public static <T> Result<T> error(int code, String message) {
            return new Result(code, message);
        }
    }

Kaedah penggunaan

  • Dua langkah di atas menentukan

    dan , kemudian mari kita lihat cara menggunakannya dalam antara muka.

    public enum ResultMsgEnum {
        SUCCESS(0, "成功"),
        FAIL(-1, "失败"),
        AUTH_ERROR(502, "授权失败!"),
        SERVER_BUSY(503, "服务器正忙,请稍后再试!"),
        DATABASE_OPERATION_FAILED(504, "数据库操作失败");
        private int code;
        private String message;
    
        ResultMsgEnum(int code, String message) {
            this.code = code;
            this.message = message;
        }
        public int getCode() {
            return this.code;
        }
        
        public String getMessage() {
            return this.message;
        }
    }

    Hasil panggilan adalah seperti berikut. Anda boleh melihat bahawa ia adalah jenis parameter yang kami takrifkan dalam Hasil. Walaupun
  • @GetMapping("/getUserName")
    public Result getUserName(){
        return Result.success("huage");
    }
boleh ditulis seperti ini untuk memenuhi keperluan harian, dan saya percaya ramai rakan menggunakannya dengan cara ini, tetapi jika kita mempunyai bilangan antara muka yang banyak, dan kemudian gunakan

dalam setiap antara muka untuk membungkus mengembalikan maklumat, Banyak kod pendua akan ditambah, yang kelihatan tidak elegan malah memalukan untuk dipamerkan. Mesti ada cara untuk memperbaiki kod sekali lagi dan mencapai penyelesaian yang optimum. 数据返回格式状态码3. Penggunaan Lanjutan

Selepas mempelajari penggunaan asas, mari kita lihat versi muktamad, yang kebanyakannya menggunakan dua mata pengetahuan berikut, sama ada ia digunakan untuk mengajar kanak-kanak perempuan , atau Memberi bimbingan kepada wanita muda adalah kemahiran yang diperlukan.

3.1 Pengenalan KelasResult.success

ResponseBodyAdvice:

Antara muka ini disediakan oleh SpringMVC 4.1, yang membenarkan data pengembalian tersuai selepas melaksanakan

Digunakan untuk merangkum pulangan format data bersatu;

  • @RestControllerAdvice: Anotasi ini adalah peningkatan kepada Pengawal dan boleh menangkap pengecualian yang dilemparkan secara global. @ResponseBody

  • 3.2 Arahan penggunaan

    Buat kelas
  • baharu;

    melaksanakan
  • antara muka , melaksanakan kaedah

    , ResponseAdvice

  • Kelas ini digunakan untuk merangkum secara seragam hasil pulangan antara muka dalam pengawal. ResponseBodyAdvicesupportsbeforeBodyWrite

    {
        "code": 0,
        "message": "成功",
        "data": "huage"
    }

    Kami boleh mengujinya melalui antara muka
  • , dan kami akan mendapati bahawa keputusan yang dikembalikan dengan menggunakan
  • secara langsung adalah konsisten.

    Walau bagaimanapun, rakan-rakan yang berhati-hati pasti menyedari bahawa dalam
  • kita semua menggunakan
untuk memproses keputusan, dan hasil jenis ralat tidak diproses. Mari kita lihat, apakah hasil pulangan apabila pengecualian berlaku? Meneruskan penggunaan kod pengecualian penuding nol HashMap di atas, keputusan ujian adalah seperti berikut:

@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<Object> {
    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 是否开启功能 true:是 
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    /**
     * 处理返回结果
     */
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        //处理字符串类型数据
        if(o instanceof String){
            try {
                return objectMapper.writeValueAsString(Result.success(o));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return Result.success(o);
    }
}
getUserNameWalaupun tiada masalah dalam format, data khusus dalam medan kod dan data adalah tidak mesra atau tidak betul. Kegagalan untuk menangani perkara ini dengan baik akan menjejaskan imej tinggi seseorang dalam minda kakak bahagian hadapan, yang tidak akan pernah diterima. Result

3.3 Pengendali Pengecualian Global

ResponseAdviceApabila kami menghadapi pengecualian pada masa lalu, perkara pertama yang kami fikirkan ialah mencuba..tangkap..akhir. Walau bagaimanapun, kaedah ini akan membawa kepada banyak perkara Pertindihan kod Masalah seperti kesukaran dalam penyelenggaraan dan logik kembung bukanlah hasil yang kita inginkan. Result.success(o)

Kaedah pengendalian pengecualian global yang akan kami gunakan hari ini agak mudah untuk digunakan. Mula-mula, tambah kelas baharu dan tambahkan anotasi

Brother Hua telah pun memperkenalkan fungsi anotasi ini di atas, jadi saya tidak akan menjelaskan butirannya lagi.

{
    "code": 0,
    "message": "成功",
    "data": {
        "timestamp": "2021-08-09T09:33:26.805+00:00",
        "status": 405,
        "error": "Method Not Allowed",
        "path": "/sysUser/getUserName"
    }
}

Jika kita mempunyai jenis pengecualian yang ingin kita pintas, tambahkan kaedah baharu dan gunakan anotasi

untuk mengubah suainya dan parameter anotasi ialah jenis pengecualian sasaran.

Contohnya: apabila Pengecualian berlaku dalam antara muka dalam pengawal, ia akan ditangkap dalam kaedah

dan maklumat pengecualian yang tidak kemas akan ditukar kepada format yang ditentukan dan diserahkan kepada @RestControllerAdvice kaedah untuk enkapsulasi format bersatu dan Kembali kepada rakan kongsi bahagian hadapan.

@RestControllerAdvice
@Slf4j
public class CustomerExceptionHandler {

    @ExceptionHandler(AuthException.class)
    public String ErrorHandler(AuthorizationException e) {
        log.error("没有通过权限验证!", e);
        return "没有通过权限验证!";
    }

    @ExceptionHandler(Exception.class)
    public Result Execption(Exception e) {
        log.error("未知异常!", e);
        return Result.error(ResultMsgEnum.SERVER_BUSY.getCode(),ResultMsgEnum.SERVER_BUSY.getMessage());
    }
}

再次调用接口getUserName查看返回结果,会发现还是有一些问题,因为我们在CustomerExceptionHandler中已经将接口返回结果封装成Result类型,而代码执行到统一结果返回类ResponseAdvice时,又会结果再次封装,就出现了如下问题。

{
    "code": 0,
    "message": "成功",
    "data": {
        "code": 503,
        "message": "服务器正忙,请稍后再试!",
        "data": null
    }
}

3.4 统一返回结果处理类最终版

解决上述问题非常简单,只要在beforeBodyWrite中增加一条判断即可。

@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<Object> {
    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 是否开启功能 true:开启
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    /**
     * 处理返回结果
     */
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        //处理字符串类型数据
        if(o instanceof String){
            try {
                return objectMapper.writeValueAsString(Result.success(o));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        //返回类型是否已经封装
        if(o instanceof Result){
            return o;
        }
        return Result.success(o);
    }
}

Atas ialah kandungan terperinci Cara mengendalikan pulangan antara muka bersatu SpringBoot dan pengecualian global. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam