国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - 聊聊springmvc中controller的方法的參數(shù)注解方式

聊聊springmvc中controller的方法的參數(shù)注解方式

2021-01-24 11:01客舟聽(tīng)雨來(lái)coding Java教程

本篇文章主要介紹了聊聊springmvc中controller的方法的參數(shù)注解方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

緒論

相信接觸過(guò)springmvc的同學(xué)都知道,在springmvc的控制層中,我們?cè)诜椒ǖ?a href="/article/84340.html">參數(shù)中可以使用注解標(biāo)識(shí)。比如下面例子:

?
1
public Map<String, Object> login(@PathVariable("loginParams") String loginParams)

@PathVariable注解就標(biāo)識(shí)了這個(gè)參數(shù)是作為一個(gè)請(qǐng)求地址模板變量的(不清楚的同學(xué)可以先學(xué)習(xí)一下restful設(shè)計(jì)風(fēng)格)。這些注解都是spring內(nèi)置注解,那么 我們可不可以自定義注解來(lái)實(shí)現(xiàn)自己的業(yè)務(wù)邏輯處理呢? 答案是可以的,spring團(tuán)隊(duì)的一大設(shè)計(jì)哲學(xué)思想就是讓自己的系統(tǒng)有無(wú)限可能性的拓展。 spring框架底層又是如何解析這些參數(shù)的注解的呢?

那么在學(xué)習(xí)自定義參數(shù)注解之前,我們先了解一下spring底層是怎么來(lái)解析這些注解參數(shù)的。實(shí)際上,這些處理過(guò)程是要涉及到配置文件的加載和解析以及一堆的各種處理,小弟功力尚淺,就分析不到那么多了,只是簡(jiǎn)單過(guò)一下。

內(nèi)置參數(shù)注解的解析

下面,我們從源碼角度來(lái)分析:

首先,sping定義了一個(gè)統(tǒng)一的方法參數(shù)注解解析接口HandlerMethodArgumentResolver,所有方法參數(shù)解析類都需要實(shí)現(xiàn)這個(gè)接口,接口很簡(jiǎn)單,定義了兩個(gè)方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface HandlerMethodArgumentResolver {
 
  /**
   * 判斷方法參數(shù)是否包含指定的參數(shù)注解
   * 含有返回true,不含有返回false
   */
  boolean supportsParameter(MethodParameter parameter);
 
  /**
   * 在給定的具體的請(qǐng)求中,把方法的參數(shù)解析到參數(shù)值里面,返回解析到的參數(shù)值,沒(méi)有返回null
   * 只有在supportsParameter返回true的時(shí)候,resolveArgument方法才會(huì)執(zhí)行
   */
  Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
      NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;
 
}

現(xiàn)在,帶著大家看看@PathVariable參數(shù)注解的解析具體過(guò)程,源代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver
    implements UriComponentsContributor {
 
    /*
     * 這里省略其它方法
     *
     /
 
  @Override
    public boolean supportsParameter(MethodParameter parameter) {
      // 不含有PathVariable注解,返回false
      if (!parameter.hasParameterAnnotation(PathVariable.class)) {
        return false;
      }
      // PathVariable注解的參數(shù)類型是Map類型
      if (Map.class.isAssignableFrom(parameter.getParameterType())) {
        String paramName = parameter.getParameterAnnotation(PathVariable.class).value();
        return StringUtils.hasText(paramName);
      }
      return true;
    }
 
   // PathVariableMethodArgumentResolver沒(méi)有重寫(xiě)resolveArgument,直接使用AbstractNamedValueMethodArgumentResolver默認(rèn)行為
   /*
   * 如果supportsParameter返回true,在這里真正處理參數(shù)
   *
   */
   protected void handleResolvedValue(Object arg, String name, MethodParameter parameter,
         ModelAndViewContainer mavContainer, NativeWebRequest request) {
 
       String key = View.PATH_VARIABLES;
       int scope = RequestAttributes.SCOPE_REQUEST;
       Map<String, Object> pathVars = (Map<String, Object>) request.getAttribute(key, scope);
       if (pathVars == null) {
         pathVars = new HashMap<String, Object>();
         request.setAttribute(key, pathVars, scope);
       }
       // 把參數(shù)的key-value放進(jìn)請(qǐng)求域,也就是把值賦給了方法參數(shù),比如請(qǐng)求路徑是: api/v1/task/{id},方法參數(shù)@PathVariable("id") String taskId,那么此時(shí)name=taskId, org=id的值
       // 當(dāng)然,怎么把請(qǐng)求地址中對(duì)應(yīng)的值獲取出來(lái),不在這篇博客的討論范疇。大家只要記得參數(shù)注解是這樣解析處理的就可以了
       pathVars.put(name, arg);
     }
 
}

AbstractNamedValueMethodArgumentResolver的resolveArgument方法如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
      NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
 
    Class<?> paramType = parameter.getParameterType();
    // 獲取請(qǐng)求參數(shù)的key-value
    NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
    // 解析參數(shù)名
    Object arg = resolveName(namedValueInfo.name, parameter, webRequest);
    if (arg == null) {
      if (namedValueInfo.defaultValue != null) {
        arg = resolveDefaultValue(namedValueInfo.defaultValue);
      }
      else if (namedValueInfo.required && !parameter.getParameterType().getName().equals("java.util.Optional")) {
        handleMissingValue(namedValueInfo.name, parameter);
      }
      arg = handleNullValue(namedValueInfo.name, arg, paramType);
    }
    else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
      arg = resolveDefaultValue(namedValueInfo.defaultValue);
    }
    // 數(shù)據(jù)綁定
    if (binderFactory != null) {
      WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
      try {
        arg = binder.convertIfNecessary(arg, paramType, parameter);
      }
      catch (ConversionNotSupportedException ex) {
        throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
            namedValueInfo.name, parameter, ex.getCause());
      }
      catch (TypeMismatchException ex) {
        throw new MethodArgumentTypeMismatchException(arg, ex.getRequiredType(),
            namedValueInfo.name, parameter, ex.getCause());
 
      }
    }
 
    /*
     * 最后的處理是交給handleResolvedValue,handleResolvedValue方法是抽象方法,我們回來(lái)看看一下PathVariableMethodArgumentResolver的handleResolvedValue方法是抽象方法的具體實(shí)現(xiàn)
     *
     */
    handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
 
    return arg;
  }

可以知道,@PathVariable標(biāo)識(shí)的參數(shù),會(huì)被對(duì)應(yīng)參數(shù)解析器把對(duì)應(yīng)值解析到一個(gè)Map結(jié)構(gòu)中保存到request scope。

總的來(lái)說(shuō),實(shí)現(xiàn)處理注解參數(shù)思路還是比較簡(jiǎn)單的,定義一個(gè)類實(shí)現(xiàn)HandlerMethodArgumentResolver接口,在對(duì)應(yīng)方法里面進(jìn)行處理就可以了。接下來(lái)我們就來(lái)一次自定義注解參數(shù)解析的實(shí)戰(zhàn)。

自定義注解參數(shù)解析演練

我們模擬一下獲取當(dāng)前任務(wù)信息。

首先我們定義一個(gè)注解

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package top.mingzhijie.demo.springmvc.anntation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/** 代表當(dāng)前任務(wù)
 * @author wunanliang
 * @date 2017/10/21
 * @since 1.0.0
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface CurrentTask {
  String value() default "";
}

接著模擬一個(gè)業(yè)務(wù)邏輯處理服務(wù)類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package top.mingzhijie.demo.springmvc.method.arguments.anntation;
 
import top.mingzhijie.demo.springmvc.entity.Task;
 
import java.util.HashMap;
import java.util.Map;
 
/**
 * 模擬任務(wù)業(yè)務(wù)類
 *
 * @author wunanliang
 * @date 2017/10/21
 * @since 1.0.0
 */
public class TaskService {
 
  private static Map<String, Task> taskMap = new HashMap<String, Task>();
 
  static {
    taskMap.put("001", new Task("task1", 10, true));
    taskMap.put("002", new Task("task2", 1, false));
    taskMap.put("003", new Task("task3", 20, false));
  }
 
  public static Task findTaskById(String taskId) {
    return taskMap.get(taskId);
  }
 
}

編寫(xiě)任務(wù)類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package top.mingzhijie.demo.springmvc.entity;
 
/**
 * @author wunanliang
 * @date 2017/10/21
 * @since 1.0.0
 */
public class Task {
 
  private String name;
  private int resolvedCount; // 參與人數(shù)
  private boolean allowStudent;
 
  public Task(){}
 
  public Task(String name, int resolvedCount, boolean allowStudent) {
    this.name = name;
    this.resolvedCount = resolvedCount;
    this.allowStudent = allowStudent;
  }
 
  public boolean isAllowStudent() {
    return allowStudent;
  }
 
  public void setAllowStudent(boolean allowStudent) {
    this.allowStudent = allowStudent;
  }
 
  public int getResolvedCount() {
    return resolvedCount;
  }
 
  public void setResolvedCount(int resolvedCount) {
    this.resolvedCount = resolvedCount;
  }
 
  public String getName() {
    return name;
  }
 
  public void setName(String name) {
    this.name = name;
  }
 
  @Override
  public String toString() {
    return "Task{" +
        "name='" + name + '\'' +
        ", resolvedCount=" + resolvedCount +
        ", allowStudent=" + allowStudent +
        '}';
  }
}

編寫(xiě)注解參數(shù)處理類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package top.mingzhijie.demo.springmvc.method.arguments.anntation;
 
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import top.mingzhijie.demo.springmvc.anntation.CurrentTask;
import top.mingzhijie.demo.springmvc.entity.Task;
 
/**
 * @author wunanliang
 * @date 2017/10/21
 * @since 1.0.0
 */
public class TaskHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
 
  public boolean supportsParameter(MethodParameter methodParameter) {
 
    boolean hasAnn = methodParameter.hasParameterAnnotation(CurrentTask.class);
    return hasAnn;
  }
 
  public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
 
    Task task = null;
    String curTaskId = (String) nativeWebRequest.getParameter("cur_task_id");
    if (curTaskId != null && !"".equals(curTaskId)) {
      task = TaskService.findTaskById(curTaskId);
    }
 
    if (task == null) {
      System.out.println("為找到對(duì)應(yīng)的任務(wù)");
    } else {
      if (task.isAllowStudent()) {
        System.out.println("當(dāng)前任務(wù)不允許學(xué)生參加哦");
      } else {
        System.out.println("學(xué)生可以參加當(dāng)前任務(wù)哦");
      }
    }
    return task;
  }
}

編寫(xiě)前端控制類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package top.mingzhijie.demo.springmvc.method.arguments.anntation;
 
import org.springframework.web.bind.annotation.*;
import top.mingzhijie.demo.springmvc.anntation.CurrentTask;
import top.mingzhijie.demo.springmvc.entity.Task;
 
import java.util.HashMap;
import java.util.Map;
 
/**
 * @author wunanliang
 * @date 2017/10/21
 * @since 1.0.0
 */
@RestController
@RequestMapping("/tasks")
public class TaskController {
 
  // 這里使用@CurrentTask來(lái)表示Task參數(shù)
  @RequestMapping(value = "/join", method = RequestMethod.GET)
  @ResponseBody
  public Map<String, Task> gJoinTask(@RequestParam("cur_task_id") String taskId, @CurrentTask Task task) {
    System.out.println(task);
    Map<String, Task> map = new HashMap<String, Task>();
    map.put("cur_task", task);
    return map;
  }
 
}

配置文件配置注解參數(shù)解析bean

?
1
2
3
4
5
<mvc:annotation-driven>
    <mvc:argument-resolvers>
      <bean class="top.mingzhijie.demo.springmvc.method.arguments.anntation.TaskHandlerMethodArgumentResolver"/>
    </mvc:argument-resolvers>
  </mvc:annotation-driven>

運(yùn)行,輸入地址 http://localhost:8888/demospringmvc/tasks/join?cur_task_id=001

獲取到任務(wù)信息json數(shù)據(jù):

?
1
2
3
4
5
6
7
{
  "cur_task": {
    "name": "task1",
    "resolvedCount": 10,
    "allowStudent": true
  }
}

可以看到,@CurrentTask標(biāo)識(shí)的參數(shù)Task,在方法中就可以獲取到經(jīng)過(guò)TaskHandlerMethodArgumentResolver處理過(guò)的任務(wù)

使用場(chǎng)景

在我們web請(qǐng)求中,往往需要客戶端待會(huì)token來(lái)進(jìn)行身份驗(yàn)證,這樣我們可以自定義參數(shù)注解來(lái)在指定的注解解析類里面來(lái)進(jìn)行token的合法性的判斷。這篇文章就到這里了~~

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://juejin.im/post/59edd553f265da432b49fddc

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久综合九色综合网站 | 久久综合狠狠综合久久综合88 | 中日韩一线二线三线视频 | 久久激情视频 | 九九九九国产 | 久久成人久久爱 | 狠狠干天天干 | 色玖玖综合 | 亚洲欧美一级久久精品国产特黄 | 国产视频一区二区在线 | 伊人春色网 | 久久小视频 | 91精品久久久久久 | 日韩成人在线播放 | 亚洲精品成人av | 亚洲第一成av人网站懂色 | 久久久精品天堂 | 成人片免费看 | 中文字幕精品一区 | 国产精品久久久久久中文字 | 中文字幕高清在线 | 黄色免费在线网站 | 青青草精品 | 色影视 | 国产精品第一国产精品 | 亚洲成人一区 | 久久噜噜噜精品国产亚洲综合 | 玖玖玖视频 | 国产欧美日韩二区 | 午夜影院网站 | 国产精品1 | 国产精品无码久久久久 | 自拍视频网站 | 黄色a一级电影 | 久草新免费 | 欧美精品网站 | 久草久| 午夜小视频在线观看 | 成人动慢 | 懂色中文一区二区在线播放 | 欧美狠狠操 |