栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

聊聊springmvc中controller的方法的参数注解方式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

聊聊springmvc中controller的方法的参数注解方式

绪论

相信接触过springmvc的同学都知道,在springmvc的控制层中,我们在方法的参数中可以使用注解标识。比如下面例子:

public Map login(@PathVariable("loginParams") String loginParams)

@PathVariable注解就标识了这个参数是作为一个请求地址模板变量的(不清楚的同学可以先学习一下restful设计风格)。这些注解都是spring内置注解,那么 我们可不可以自定义注解来实现自己的业务逻辑处理呢? 答案是可以的,spring团队的一大设计哲学思想就是让自己的系统有无限可能性的拓展。 spring框架底层又是如何解析这些参数的注解的呢?

那么在学习自定义参数注解之前,我们先了解一下spring底层是怎么来解析这些注解参数的。实际上,这些处理过程是要涉及到配置文件的加载和解析以及一堆的各种处理,小弟功力尚浅,就分析不到那么多了,只是简单过一下。

内置参数注解的解析

下面,我们从源码角度来分析:

首先,sping定义了一个统一的方法参数注解解析接口HandlerMethodArgumentResolver,所有方法参数解析类都需要实现这个接口,接口很简单,定义了两个方法:

public interface HandlerMethodArgumentResolver {

  
  boolean supportsParameter(MethodParameter parameter);

  
  Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
      NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;

}

现在,带着大家看看@PathVariable参数注解的解析具体过程,源代码如下:

public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver
    implements UriComponentsContributor {

    
   protected void handleResolvedValue(Object arg, String name, MethodParameter parameter,
  ModelAndViewContainer mavContainer, NativeWebRequest request) {

String key = View.PATH_VARIABLES;
int scope = RequestAttributes.SCOPE_REQUEST;
Map pathVars = (Map) request.getAttribute(key, scope);
if (pathVars == null) {
  pathVars = new HashMap();
  request.setAttribute(key, pathVars, scope);
}
// 把参数的key-value放进请求域,也就是把值赋给了方法参数,比如请求路径是: api/v1/task/{id},方法参数@PathVariable("id") String taskId,那么此时name=taskId, org=id的值
// 当然,怎么把请求地址中对应的值获取出来,不在这篇博客的讨论范畴。大家只要记得参数注解是这样解析处理的就可以了
pathVars.put(name, arg);
     }

}

AbstractNamedValueMethodArgumentResolver的resolveArgument方法如下

public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
      NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

    Class paramType = parameter.getParameterType();
    // 获取请求参数的key-value
    NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
    // 解析参数名
    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);
    }
    // 数据绑定
    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());

      }
    }

    
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface CurrentTask {
  String value() default "";
}

接着模拟一个业务逻辑处理服务类

package top.mingzhijie.demo.springmvc.method.arguments.anntation;

import top.mingzhijie.demo.springmvc.entity.Task;

import java.util.HashMap;
import java.util.Map;


public class TaskService {

  private static Map taskMap = new HashMap();

  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);
  }

}

编写任务类

package top.mingzhijie.demo.springmvc.entity;


public class Task {

  private String name;
  private int resolvedCount; // 参与人数
  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 +
 '}';
  }
}

编写注解参数处理类

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;


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("为找到对应的任务");
    } else {
      if (task.isAllowStudent()) {
 System.out.println("当前任务不允许学生参加哦");
      } else {
 System.out.println("学生可以参加当前任务哦");
      }
    }
    return task;
  }
}

编写前端控制类

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;


@RestController
@RequestMapping("/tasks")
public class TaskController {

  // 这里使用@CurrentTask来表示Task参数
  @RequestMapping(value = "/join", method = RequestMethod.GET)
  @ResponseBody
  public Map gJoinTask(@RequestParam("cur_task_id") String taskId, @CurrentTask Task task) {
    System.out.println(task);
    Map map = new HashMap();
    map.put("cur_task", task);
    return map;
  }

}

配置文件配置注解参数解析bean


    
      
    
  

运行,输入地址 http://localhost:8888/demospringmvc/tasks/join?cur_task_id=001

获取到任务信息json数据:

{
  "cur_task": {
    "name": "task1",
    "resolvedCount": 10,
    "allowStudent": true
  }
}

可以看到,@CurrentTask标识的参数Task,在方法中就可以获取到经过TaskHandlerMethodArgumentResolver处理过的任务

使用场景

在我们web请求中,往往需要客户端待会token来进行身份验证,这样我们可以自定义参数注解来在指定的注解解析类里面来进行token的合法性的判断。这篇文章就到这里了~~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/143582.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号