SpringMVC框架

关于SpringMVC框架

  • SpringMVC框架的基础依赖项是spring-webmvc

  • SpringMVC框架主要解决了接受请求,响应结果级相关问题

关于控制器

  • 控制器(Controller)是用于接收请求,响应结果的。

  • 在类上添加@Controller即可将此类标记为''控制器类''。

  • 默认情况下,Spring MVC框架处理响应时,并不是“响应正文”的,各方法的返回值表示"视图组件的名称”,也就是说,每次处理完请求后,Spring MVC框架还应该处理一个视图”,最终,将”视图"响应到客户端去,这不是前后端分离的做法。

  • 目前,主流的开发模式是前后端分离的,更加适用于多种不同额客户端软件的项目中,在这种模式下,当服务器每次处理完请求后,只需要将结果(数据)响应到客户端,由客户端去决定如何识别,使用所响应的数据。

  • 在处理请求的方法上添加@ResponseBody注解,即可使得此方法是''响应正文''的,即方法的返回值会直接响应到客户端去,就符合前后端分离模式。

  • 也可以将@ResponseBody添加在控制器类上,则当前类中所有处理请求的方法都是"响应正文"的。

  • 在开发实践中,通常选择在类上添加@RestController注解,此注解使用了@Controller和@ResponseBody作为其元注解,同时具有这2个注解的效果,其源代码:

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

关于@RequestMapping注解

  • 在Spring MVC框架中,提供了@ResquestMapping注解,主要用于配置请求路径处理请求方法的映射关系。

  • 还可以在控制器类上添加@ResquestMapping注解,当配置了某个路径值后,此路径值将作为当前控制器类中的每个处理请求的URL的前缀部分,例如,在类上的配置值是/album,在方法上的配置值是/add-new,则完整的URL就是/album/add-new。

  • 提示:如果在控制类和方法上都使用@RequestMapping配置了URL,框架会自动处理必要和多余的/,例如:

在类上使用@RequestMapping的配置值

在方法上使用@RequestMapping的配置值

/album

/add-new

/album

add-new

album

/add-new

album

add-new

/album/

/add-new

/album/

add-new

album/

/add-new

album/

add-new

以上配置的组合都是等效的,通常推荐使用以上第一种和第四种。

  • 在@RequestMapping注解的源代码中有:

String[] value() default {};

以上代码表示:

  • value():表示此注解可以配置名为 value的属性

  • string[]: 表示此属性的值是 string[]类型的

  • default : 表示此属性的默认值是空数组

所以,在使用使,可以配置为:

@RequestMapping(value={'a','b'})
  • 在Java语言中,如果需要配置的注解参数的属性名是value,且只配置这一个属性时,可以不必显示声明属性名称,即:

@RequestMapping(value={'a','b'})
@RequestMapping({'a','b'})

以上两种写法是完全等效的!

  • 在Java语言中,如果需要配置的注解属性的值是某种数组,但是,需要使用的数组值中只有一个元素时,可以不必使用大括号将其框住,即:

@RequestMapping({'a'})
@RequestMapping('a')

以上两种写法是完全等效的!

  • 在@RequestMapping的源代码有:

 @AliasFor("path")//关注
    String[] value() default {};
  • 以上@AliasFor表示"等效于",在@RequestMapping的源代码还有:

 @AliasFor("value")
    String[] path() default {};
  • 另外,在@RequestMapping的源代码中有:

RequestMethod[] method() default {};
//RequestMapping的几种请求方式
public enum RequestMethod {
    GET,
    HEAD,
    POST,
    PUT,
    PATCH,
    DELETE,
    OPTIONS,
    TRACE;
}
  • 以上属性用户"限制客户端提交请求时的请求方式",如果没有配置此属性,则所有的请求方式都是允许的,如果进行限制,则只允许特定的请求方式,如果使用了不匹配的请求方式,将响应 405,例如,配置为:

@RequestMapping(value = "/he11o",method = RequestMethod.POST)
  • 当提交GET类型的请求时,服务器端将响应:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Feb 23 11:35:10 CST 2023
There was an unexpected error (type=Method Not Allowed, status=405).
@RequestMapping(value = "/he11o",method = {RequestMethod.POST,RequestMethod.GET})
  • 以上代码表示既可以提交POST请求,也可以提交GET请求。

  • 并且,如果存在2个配置,只要请求方式不同,URL允许相同!例如:

@RequestMapping(value = "/he11o",method = RequestMethod.POST)
public string he11o1() {
  //...
}
@RequestMapping(value = "/he11o",method = RequestMethod.GET)
public string he11o2() {
  //...
}
  • 在SpringMVC框架中,提供了一些基于@RequestMapping的其他注解,例:

  • @GetMapping

  • @PostMapping

  • @PutMapping

  • @DeleteMapping

  • @PatchMapping

开发实践小结

  • 在控制器类上推荐使用的是@RestController

  • 在控制器类中推荐使用@RequestMapping配置URL前缀部分

  • 各处理请求的方法上推荐使用@GetMapping等限制了请求方式的注解来配置URL

统一处理异常

  • SpringMVC框架中提供了统一处理异常的机制,可以实现"对于每种异常,只需要编写一次处理此异常的代码即可,无论在处理哪个请求的过程中出现此异常,都会通过同一段代码进行处理"

  • 关于统一处理异常的方法:

  • 注解:@ExceptionHandler--异常处理器

  • 返回值类型:参考处理请求的方法

  • 方法名:参考处理请求的方法

  • 参数列表:必须包含异常类型的参数,表示需要被处理的异常,并且,只能按需添加HttpServletResquest/HttpServletResponse等少量特定类型的参数,不可以随意添加其他参数,当方法有多个参数时,各参数可以不区分先后顺序

  • 方法一:直接在异常方法上加@ExceptionHandler

@ExceptionHandler
    public JsonResult handlerServiceException(ServiceException e){
        return JsonResult.fail(ServiceCode.error, "出错啦");
    }
 @Test
    void handler(){
        try{
            //controller.xxx();
        } catch (Exception e){
            //统一处理
        }
    }

则当前类中任何处理请求的方法不再需要处理 serviceException,如果执行过程中出现了serviceException,都会由以上方法进行处理!

需要注意:当把处理异常的方法定义在控制器类中时,仅作用于当前控制器类中所有处理请求的方法,无法作用于其它控制器类中处理请求的方法!

  • 方法二(自定义类)

  • 方法三(推荐)

  • 应该自定义类,在类上添加@ControllerAdvice注解,则此类中特定的方法(例如添加了@ExceptionHandler注解的方法)将作用于Spring MVC框架处理每个请求的过程中,例如:

  • 使用@ControllerAdvice注解后就不需要在别的Controller继承这个类了

  • 另外,也可以使用@RestControllerAdvice来取代@ControllerAdvice与@ResponseBody,例如:

  • 在处理异常的类中,关于处理异常的方法:

  • 允许同时存在若干个处理异常的方法,但各方法处理的异常必须不同

  • 多个处理不同异常的方法,所处理的异常允许存在父子级关系,在实际处理时,优先按照最匹配的类型的方法进行处理

  @ExceptionHandler
    public JsonResult handlerServiceException(ServiceException e){
        return JsonResult.fail(ServiceCode.error, "出错啦");
    }
    @ExceptionHandler
    public JsonResult handlerNullPointerException(NullPointerException e){
        return JsonResult.fail(ServiceCode.error, "你的程序出现了空指针异常");
    }
    @ExceptionHandler
    public JsonResult handlerRuntimeException(RuntimeException e){
        return JsonResult.fail(ServiceCode.error, "你的程序出现了RuntimeException异常");
    }
  • 强烈建议添加处理Throwable 类型异常的方法,避免向客户端响应500错误

  • 在此方法中,应该记录异常的类型和关键信息,并且,执行到此方法时,应该及时添加新的、处理对应异常的方法

 @ExceptionHandler
    public JsonResult handlerThrowable(Throwable e){
        String message = "服务器忙,请稍后再次尝试! (开发过程中,如果看到此提示,请检查控制台的信息,并补充处理异常的方法)";
        //注意:在生产环境中,禁止使用此语句
        e.printStackTrace();//打印异常信息
        return JsonResult.fail(ServiceCode.error, message);
    }
  • 另外,关于异常信息的描述,应该是“谁抛出,谁描述”的原则,所以,应该在 serviceException类中添加带string message的构造方法,并且通过父级类别的构造方法将参数用于对detailMessage属性(定义在Throwable类中)赋值,后续,可以通过getMessage0 方法获取此值,例如:

public class ServiceException extends RuntimeException{
    public ServiceException(String message) {
        super(message);
    }
  • 然后,在业务实现过程中,当需要抛出异常时,封装描述文本,例如:

// 判断查询结果是否为null
        if(albumStandardVO==null){
            String message = "删除相册失败,尝试删除的相册数据不存在!";
            // 是:数据不存在,抛出异常
            log.warn("尝试删除的相册数据不存在,即将抛出异常");
            throw new ServiceException(message);
        }
  • 后续,在全局异常处理器中,通过异常对象可以获取所封装的描述文本,例如:

  @ExceptionHandler
    public JsonResult handlerServiceException(ServiceException e){
        return JsonResult.fail(ServiceCode.error, e.getMessage());
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值