这篇文章给大家分享的是有关springMVC中controller参数注解的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。绪论相信接触过springmvc的同学都知道,在springmvc的控制层中,我们
这篇文章给大家分享的是有关springMVC中controller参数注解的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
绪论
相信接触过springmvc的同学都知道,在springmvc的控制层中,我们在方法的参数中可以使用注解标识。比如下面例子:
public Map<String, Object> 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<String, Object> pathVars = (Map<String, Object>) request.getAttribute(key, scope); if (pathVars == null) { pathVars = new HashMap<String, Object>(); 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<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); }}
编写任务类
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<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; }}
配置文件配置注解参数解析bean
<mvc:annotation-driven> <mvc:argument-resolvers> <bean class="top.mingzhijie.demo.springmvc.method.arguments.anntation.TaskHandlerMethodArgumentResolver"/> </mvc:argument-resolvers> </mvc:annotation-driven>
运行,输入地址 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的合法性的判断。
感谢各位的阅读!关于“springmvc中controller参数注解的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
--结束END--
本文标题: springmvc中controller参数注解的示例分析
本文链接: https://lsjlt.com/news/222188.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0