学生程序设计能力提升平台源码分析(四)Controller层源码分析之收尾篇

前言

2021SC@SDUSC

概述

本篇博客继续上次的话题,对项目Controller层源码分析进行收尾

源码

源码如下:

​


@RestController
@RequestMapping("/problemset")
public class ProblemsetController {

    @Autowired
    private ProblemsetService problemsetService;

    @Autowired
    private ProblemService problemService;

    private final Logger log = LoggerFactory.getLogger(ProblemController.class);


    @PostMapping("/getProblemset")
    @PreAuthorize("hasRole('ROLE_COMMON')")
    public ResultEntity getProblemset(@RequestParam("id") int id) {
        try {
            Problemset problemset = problemsetService.getProblemset(id);
            List<Problem> problemList = problemsetService.getProblemList(id);
            problemset.setProblems(problemList);
            return ResultEntity.success("题目集", problemset);
        } catch (Exception e) {
            log.error("查看题目集错误", e);
            return ResultEntity.error("查看题目集错误,请重试");
        }
    }

}

​

在上一篇博客中已经分析了@Autowired实现原理,slf4j日志,@PostMapping实现原理等

下面我们将对剩余关键点进行分析,其实就是对:
1.@PreAuthorize("hasRole('ROLE_COMMON')")

2.@RequestParam("id") int id

3. return ResultEntity

三个部分进行分析

@PreAuthorize实现原理

@PreAuthorize注解来自于SpringSecurity,是SpringSecurity提供的权限安全认证注解。是在进入方法前进行权限验证,@PreAuthorize 声明这个方法所需要的权限表达式

使用方法

hasRole:

角色授权:授权代码,在我们返回的UserDetails的Authority需要加ROLE_前缀,Controller上使用时不要加前缀,例如:

hasAuthority:

权限授权:用户自定义的权限,返回的UserDetails的Authority只要与这里匹配就可以,这里不需要加ROLE_,名称保持一至即,例如:

其余使用不如上面两个频繁:

源代码

package org.springframework.security.access.prepost;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface PreAuthorize {
    String value();
}

分析原理

这里我们以hasAuthority()方法为示例,其余方法的原理大同小异:
原理就是:根据这个注解所需要的权限,再和当前登录的用户角色所拥有的权限对比,如果用户的角色权限集Set中有这个权限,则放行;没有,拒绝

所需要的权限由注解参数传递,登录角色拥有的权限由spring security控制,在用户login的时候已经获取并保存

详细代码流程:

hasAuthority代码流程

@RequestParam实现原理

使用方法

@RequestParam可以将请求参数绑定到控制器的方法参数上,规定了方法所接受的参数列表

语法:@RequestParam(value=”参数名”,required=”true/false”,defaultValue=””)

value:参数名
required:是否包含该参数,默认为true,表示该请求路径中必须包含该参数,如果不包含就报错。
defaultValue:默认参数值,如果设置了该值,required=true将失效,自动为false,如果没有传该参数,就使用默认值

例子:

源代码

package org.springframework.web.bind.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;

    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}

分析原理

简单来说就是通过 request.getParameter() 方法去获取参数值,然后对 @RequestParam 中的属性进行比对,实现由注解到底层代码的封装

具体封装流程:

@RequestParam 代码流程

ResultEntity实现原理

使用方法

作为controller层返回参数的实体类,可以return resultEntity.success()或者return resultEntity.error()控制返回的类型,通过不同的参数列表实现不同的返回效果,例如:
 

return ResultEntity.success("公开题目集", problemsets);

return ResultEntity.error("查看公开题目集错误,请重试");

return ResultEntity.success("题目集添加成功");

等等

源代码

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;

public class ResultEntity {
    @JSONField(ordinal = 1)
    private int code;
    @JSONField(ordinal = 2)
    private String message;
    @JSONField(ordinal = 3)
    private Object data;

    public ResultEntity(int code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static ResultEntity success() {
        return new ResultEntity(0, "success", true);
    }

    public static ResultEntity success(String message) {
        return new ResultEntity(0, message, null);
    }

    public static ResultEntity success(String message, Object data) {
        return new ResultEntity(0, message, data);
    }

    public static ResultEntity data(Object data) {
        return success("success", data);
    }

    public static ResultEntity data(){
        return success("success");
    }

    public static ResultEntity error(String message) {
        return new ResultEntity(-1, message, null);
    }

    public static ResultEntity error(String message, Object data) {
        return new ResultEntity(-1, message, data);
    }

    public static ResultEntity error(int code, String message) {
        return new ResultEntity(code, message, null);
    }

    public static ResultEntity error(StatusCode entity){
        return new ResultEntity(entity.getCode(), entity.getMessage(), null);
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return JSONObject.toJSONString(this);
    }
}

分析原理

内置code,message,data的实体类,通过不同的构造参数实现不同的数据封装,并作为返回体返回请求的结果

总结

controller层的源码分析就到此为止了,可以看出来一些注解和类的底层实现机制还是比较复杂的,了解其实现原理对我们提高代码分析和开发能力有一定帮助。

下一篇分析预计会对service层代码进行分析,感谢阅读。

参考资料

@RequestParam注解使用_一叶知秋-CSDN博客_@requestparam

Spring Security - @PreAuthorize安全表达式hasRole、hasAuthority区别_LeoSong121的博客-CSDN博客Spring Security @PreAuthorize 权限控制的原理_u010227042的博客-CSDN博客Spring Security - @PreAuthorize安全表达式hasRole、hasAuthority区别_LeoSong121的博客-CSDN博客

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值