成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

完全自定義實現SpringMVC核心組件

開發 前端
實際Spring Web底層是做了很多的工作,其核心組件有HandlerMapping, HandlerAdapter, ViewResolver等組件。

概述

通過Spring定義請求接口非常容器,通過幾個注解就可以完成,如下:

@RestController
@RequestMapping("/demos")
public class DemoController {
@GetMapping("/index")
public Object index() {
return "index" ;
}
}

通過上面的@RestController, @RequestMapping就完成了一個簡單的接口定義。

實際Spring Web底層是做了很多的工作,其核心組件有HandlerMapping, HandlerAdapter, ViewResolver等組件。

  1. HandlerMapping
    根據當前請求的URI,查找對應的Handler,如:HandlerExecutionChain,包裝的HandlerMethod
  2. HandlerAdapter
    根據上面的確定的HandlerMethod, 找到能夠處理該Handler的Adapter,進行調用
  3. ViewResolver
    如果返回的ModelAndView對象那么會通過相應的ViewResolver進行渲染輸出

了解了上面的幾個核心組件之后,接下來就是自定義實現上面的核心類,來完成接口的請求處理。

自定義Endpoint

自定義注解,標記Controller類及請求參數:

 @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PackEndpoint {
}

參數標記,用來對接口參數進行注解。

 @Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PackParam {
}

Endpoint接口參數封裝對象

該對象用來保存記錄,方法參數由@PackParam注解的參數。

public class PackMethodParameter {
// 用來解析接口參數的名稱
private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer() ;
private String name ;
private Executable executable ;
private int parameterIndex ;
private Class<?> type ;
public PackMethodParameter(String name, int parameterIndex, Executable executable) {
this.name = name;
this.parameterIndex = parameterIndex ;
this.executable = executable ;
}
public PackMethodParameter(int parameterIndex, Executable executable, Class<?> type) {
this.parameterIndex = parameterIndex ;
this.executable = executable ;
this.type = type ;
}
public boolean hasParameterAnnotation(Class<? extends Annotation> clazz) {
Method method = (Method) this.executable ;
Parameter[] parameters = method.getParameters() ;
return parameters[this.parameterIndex].isAnnotationPresent(clazz) ;
}
public String getParameterName() {
String[] parameterNames = parameterNameDiscoverer.getParameterNames((Method) this.executable) ;
return parameterNames[this.parameterIndex] ;
}
}

自定義HandlerMapping

自定義實現了SpringMVC標準的HandlerMapping,這樣在DispatcherServlet中才能夠識別。

public class PackHandlerMapping implements HandlerMapping, InitializingBean, ApplicationContextAware {
private ApplicationContext context;
private Map<String, PackMethodHandler> mapping = new HashMap<>();
@Override
public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
String requestPath = request.getRequestURI();
Optional<PackMethodHandler> opt = mapping.entrySet().stream().filter(entry -> entry.getKey().equals(requestPath)).findFirst()
.map(Map.Entry::getValue);
if (opt.isPresent()) {
HandlerExecutionChain executionChain = new HandlerExecutionChain(opt.get()) ;
return executionChain ;
}
return null;
}
// Bean初始化時,從容器中查找所有符合條件的Bean對象,即Bean對象上有@PackEndpoint注解
@Override
public void afterPropertiesSet() throws Exception {
String[] beanNames = context.getBeanNamesForType(Object.class) ;
for (String beanName : beanNames) {
Object bean = this.context.getBean(beanName) ;
Class<?> clazz = bean.getClass() ;
// 判斷當前的Bean上是否有PackEndpoint注解,只對有該注解的類進行處理
if (clazz.getAnnotation(PackEndpoint.class) != null) {
RequestMapping clazzMapping = clazz.getAnnotation(RequestMapping.class) ;
String rootPath = clazzMapping.value()[0] ;
if (clazzMapping != null) {
ReflectionUtils.doWithMethods(clazz, method -> {
RequestMapping nestMapping = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class) ;
if (nestMapping != null) {
String nestPath = nestMapping.value()[0] ;
String path = rootPath + nestPath ;
PackMethodHandler handler = new PackMethodHandler(method, bean) ;
mapping.put(path, handler) ;
}
}) ;
}
}
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
// 該類的作用:用來記錄接口對應的信息,方法,對應的實例,參數信息
public static class PackMethodHandler {
private Method method;
private Object instance;
private PackMethodParameter[] parameters ;
public Method getMethod(){
return method;
}
public void setMethod(Method method){
this.method = method;
}
public Object getInstance(){
return instance;
}
public void setInstance(Object instance){
this.instance = instance;
}
public PackMethodHandler(Method method, Object instance){
super();
this.method = method;
this.instance = instance;
Parameter[] params = method.getParameters() ;
this.parameters = new PackMethodParameter[params.length] ;
for (int i = 0; i < params.length; i++) {
this.parameters[i] = new PackMethodParameter(i, method, params[i].getType()) ;
}
}
public PackMethodParameter[] getParameter() {
return this.parameters ;
}
}
}

自定義參數解析器

專門用來解析處理接口方法中的參數信息然后從請求中讀取。

public interface PackHandlerMethodArgumentResolver {
boolean supportsParameter(PackMethodParameter methodParameter);
Object resolveArgument(PackMethodParameter methodParameter, HttpServletRequest request);
}
public class PackParamHandlerMethodArgumentResolver implements PackHandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(PackMethodParameter methodParameter){
return methodParameter.hasParameterAnnotation(PackParam.class) ;
}
@Override
public Object resolveArgument(PackMethodParameter methodParameter, HttpServletRequest request){
String name = methodParameter.getParameterName() ;
Object arg = null;
String[] parameterValues = request.getParameterValues(name) ;
if (parameterValues != null) {
arg = parameterValues.length == 1 ? parameterValues[0] : parameterValues ;
}
return arg ;
}
}

自定義HandlerAdapter

自定義實現了SpringMVC標準的HandlerAdatper,這樣在DispatcherServlet中才能夠識別。

public class PackHandlerAdapter implements HandlerAdapter{
@Resource
private ConversionService conversionService ;
private PackParamHandlerMethodArgumentResolver argumentResolver = new PackParamHandlerMethodArgumentResolver() ;
@Override
public boolean supports(Object handler){
return handler instanceof PackMethodHandler;
}
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
PackMethodHandler methodHandler = (PackMethodHandler) handler ;
PackMethodParameter[] parameters = methodHandler.getParameter() ;
Object[] args = new Object[parameters.length] ;
for (int i = 0; i < args.length; i++) {
if (this.argumentResolver.supportsParameter(parameters[i])) {
// 解析對應的方法參數
args[i] = this.argumentResolver.resolveArgument(parameters[i], request) ;
// 類型轉換
args[i] = this.conversionService.convert(args[i], parameters[i].getType()) ;
}
}
// 調用目標方法
Object result = methodHandler.getMethod().invoke(methodHandler.getInstance(), args) ;
// 設置響應header,輸出內容
response.setHeader("Content-Type", "text/plain;charset=utf8") ;
PrintWriter out = response.getWriter() ;
out.write((String) result) ;
out.flush() ;
out.close() ;
return null ;
}
@Override
public long getLastModified(HttpServletRequest request, Object handler){
return -1 ;
}

}

通過以上的步驟就完成了一個完全自定義SpringMVC核心組件的實現。

責任編輯:姜華 來源: 今日頭條
相關推薦

2022-03-01 16:09:06

OpenHarmon鴻蒙單選組件

2023-01-03 07:40:27

自定義滑塊組件

2020-11-11 08:04:34

低代碼

2022-04-24 15:17:56

鴻蒙操作系統

2023-02-20 15:20:43

啟動頁組件鴻蒙

2009-06-24 15:13:36

自定義JSF組件

2022-01-17 10:20:24

Ubuntu桌面Linux

2022-10-26 15:54:46

canvas組件鴻蒙

2022-10-25 15:12:24

自定義組件鴻蒙

2022-02-21 15:16:30

HarmonyOS鴻蒙操作系統

2022-06-20 15:43:45

switch開關鴻蒙

2021-12-21 15:22:22

鴻蒙HarmonyOS應用

2021-11-01 10:21:36

鴻蒙HarmonyOS應用

2022-05-18 07:44:13

自定義菜單前端

2022-07-06 20:24:08

ArkUI計時組件

2009-06-25 14:53:35

自定義UI組件JSF框架

2022-07-15 16:45:35

slider滑塊組件鴻蒙

2021-09-15 10:19:15

鴻蒙HarmonyOS應用

2022-06-30 14:02:07

鴻蒙開發消息彈窗組件

2022-10-17 14:39:12

自定義彈窗組件鴻蒙
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 少妇av片 | 亚洲国产成人精品久久久国产成人一区 | 一级爱爱片 | 中文字幕综合 | 超碰操 | 亚洲欧美日韩精品久久亚洲区 | 在线免费观看亚洲 | 日韩无| 国产成人免费在线 | 91精品国产91久久久久游泳池 | 久久夜夜| 国产精品99久久久久久久vr | 久久精品com | 欧美精品二区 | a国产视频 | 欧美精品三区 | 91精品国产一区 | 日韩黄| 国产综合精品一区二区三区 | 黄色三级在线播放 | 亚洲午夜精品一区二区三区 | 中文字幕一区二区三区四区 | 一区二区三区免费观看 | 日韩1区2区 | 色婷婷久久久久swag精品 | www天天操| 日韩欧美专区 | 欧美精品久久久久久久久老牛影院 | 亚洲精品免费观看 | av中文在线播放 | 欧美日韩亚洲国产综合 | 91精品国产乱码久久久久久久久 | 国产成人a亚洲精品 | 精品国产精品三级精品av网址 | 亚洲成人一区二区 | 激情 婷婷 | 国产欧美在线 | 国产美女精品 | 国产成人精品网站 | 欧美在线 | 99福利视频 |