This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Spring MVC 支持

Restlight支持了Spring MVC的使用习惯,你可以按照Spring MVC的方式使用Restlight

引入依赖

<dependency>
	<groupId>io.esastack</groupId>
	<artifactId>restlight-springmvc-provider</artifactId>
	<version>${restlight.version}</version>
</dependency>

1 - Spring MVC 注解支持

支持的注解

  • @Controller
  • @RestController
  • @RequestMapping
  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping
  • @ResponseStatus
  • @ControllerAdvice
  • @ExceptionHandler
  • @RequestParam
  • @RequestHeader
  • @PathVariable
  • @CookieValue
  • @MatrixVariable
  • @RequestAttribute

注解能力扩展

@RequestParam, @ReqeustHeader,@PathVariable,@CookieValue, @MatrixVariable,@RequestAttribute

参数绑定相关注解除SpringMVC用法外,同时支持

Constructor接收一个String类型的参数

eg.

public void foo(@RequestParam User user) {
    //...
}

static class User {
    final String name;
    public User(String str) {
        this.name = name;
    }
}

存在静态的valueOf()或者fromString()方法

eg.

public void foo(@RequestParam User user, @RequestHeader Car car) {
    //...
}

static class User {
    String name;
    
    public static User valueOf(String str) {
        User user = new User();
        user.name = name;
        return user;
    }
}

static class Car {
    String name;
    
    public static Car fromString(String str) {
        Car car = new Car();
        car.name = name;
        return car;
    }
}

个别注解说明

@RequestParam

除普通用法外, 当未指定value()或者name且参数对象为Map<String, List<String>类型时, 将整个ParameterMap(即AsyncRequest.getParameterMap)作为参数的值。

eg.

public void foo(@RequestParam Map<String, List<String> params) {
    //...
}

@CookieValue

普通String类型

public void foo(@CookieValue String c) {
    //...
}

Cookie对象(io.netty.handler.codec.http.cookie.Cookie)

public void foo(@CookieValue Cookie c) {
    //...
}

获取所有的Cookie

public void foo(@CookieValue Set<Cookie> cookies) {
    //...
}

@RequestHeader

除获取单个header之外, 可以如果参数类型为io.netty.handler.codec.http.HttpHeaders则以所有的Header作为参数的值

eg:

public void foo(@RequestHeader HttpHeaders headers) {
    //...
}

2 - ExceptionHandler支持

Restlight支持业务自定义异常处理逻辑。对于Controller方法中抛出的异常,处理逻辑和顺序如下(注意:一个异常只会被处理一次):

1.尝试在Controller内部查找异常处理方法来处理当前异常,未找到进入2 2.尝试寻找全局异常处理方法来处理当前异常,未找到则返回错误信息

Controller级异常处理

局部异常处理方法只能处理当前Controller中抛出的异常,示例如下:

@RestController
@RequestMapping("/exception")
public class LocalExceptionResolver {

    @RequestMapping("/willBeHandled")
    public void willBeHandled() {
        throw new IllegalArgumentException("IllegalArgumentException...");
    }

    @RequestMapping("/willNotBeHandled")
    public void willNotBeHandled() {
        throw new RuntimeException("RuntimeException...");
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public String handleLocalException(IllegalArgumentException ex) {
        return "HandleLocalException [" + ex.getMessage() + "]";
    }
}

handleLocalException(XXX)方法会处理当前类中所有的IllegalArgumentException异常。

@ControllerAdvice全局异常处理

通过@ControllerAdvice@RestControllerAdvice来标识全局异常处理类,并可通过相应的属性设置该全局异常处理类生效的范围。使用示例如下:

@RestControllerAdvice(basePackages = {"esa.restlight.samples.starter.exceptionhandler", "esa.restlight.samples.starter.controller"})
public class GlobalExceptionResolver {

    @ExceptionHandler(Exception.class)
    public Result handleException(Exception ex) {
        return Result.ok();
    }

    static class Result {
        private int status;
        private String msg;

        static Result ok() {
            Result r = new Result();
            r.status = 200;
            return r;
        }
        
        // getter and setter
    }

}

如上所示, handleException(XXX)方法会处理esa.restlight.samples.starter.exceptionhandleresa.restlight.samples.starter.controller包中抛出的所有Exception

高级使用

为了让用户更方便的使用异常处理, 类似的我们支持像Controller上一样的去使用一些注解的功能如 @RequestParam, @RequestHeader@CookieValue等方便的进行参数绑定而不是自己手动的去Request里面取并做一次参数转换的操作。

eg:

@ControllerAdvice
public class GlobalExceptionResolver {

    @ExceptionHandler(Exception.class)
    public String handleException(@RequestParam("foo") String foo, Exception ex) {
        // do something here...
        return "HandleGlobalException [" + ex.getMessage() + "]";
    }

}

异步异常处理器

异常处理器可以类似Controller中异步处理一样完成异步的处理 Restlight异步支持

  • CompletableFuture
  • ListenableFuture(Guava)
  • Future(io.netty.util.concurrent.Future)

使用CompletableFuture异步方式:

@ExceptionHanlder(Exception.class)
public CompletableFuture<String> handleExcption(Exception ex) {
    return CompletableFuture.supplyAsync(() -> {
        // ...
        return "Hello Restlight!";
    });
}

ListenableFuture(Guava)Future(io.netty.util.concurrent.Future)同理。