首页 > 其他分享 >SpringMvc 原理解析

SpringMvc 原理解析

时间:2023-04-19 22:02:05浏览次数:39  
标签:null SpringMvc handler args else attrName webRequest 原理 解析

springMVC源码流程

image.png

  • 第一步 先来到DispatcherServlet () @SuppressWarnings("serial") public class DispatcherServlet extends FrameworkServlet
  • 来到doDispatch 的方法 doDispatch(HttpServletRequest request, HttpServletResponse response)
  • 进入
//1. 先检查时候文件上传请求
processedRequest = checkMultipart(request);
multipartRequestParsed = processedRequest != request;

//2.根据当前请求地址值类哪个先处理 Determine handler for the current request.
mappedHandler = getHandler(processedRequest);

//3. 找到处理器 找不到抛出异常
mappedHandler = getHandler(processedRequest);
			if (mappedHandler == null || mappedHandler.getHandler() == null) {
	noHandlerFound(processedRequest, response);
	return;
}

//4. 拿到适配器/(反射工具) Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

//5.适配器来执行目标方法;将目标方法执行完成后的返回值作为视图名,设置保存到ModelAndView中,目标方法无论怎么写,最终适配器执行完成以后都会将执行后的信息封装成ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

//6、根据方法最终执行完成后封装的ModelAndView;转发到对应页面,而且ModelAndView中的数据可以从请求域中获取
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

doDispatch()详细细节:

1)所有请求过来DispatcherServlet收到请求, 2)调用doDispatch()方法进行处理 1)getHandler():根据当前请求地址找到能处理这个请求的目标处理器类(处理器) 根据当前请求在HandlerMapping中找到这个请求的映射信息,获取到目标处理器类

2)getHandlerAdapter():根据当前处理器类获取到能执行这个处理器方法的适配器; 根据当前处理器类,找到当前类的HandlerAdapter(适配器)

3)使用刚才获取到的适配器(AnnotationMethodHandlerAdapter )执行目标方法;

4)目标方法执行后会返回一个ModelAndView对象

5)根据ModelAndView的信息转发到具体的页面,并可以在请求域中取出ModelAndView中的模型数据

getHandler()细节:怎么根据当前请求就能找到哪个类能来处理

  • getHandler()会返回目标处理器类的执行链mappedHandler image.png image.png

如何找到目标处理器类的适配器。要拿适配器才去执行目标方法

image.png ///// image.png image.png

DispatcherServlet中有几个引用类型的属性;SpringMVC的九大组件

SpringMVC在工作的时候,关键位置都是由这些组件完成的; 共同点:九大组件全部都是接口;接口就是规范;提供了非常强大的扩展性; SpringMVC的九大组件工作原理;

 /** 文件上传解析器*/
private MultipartResolver multipartResolver;
/** 区域信息解析器;和国际化有关 */
private LocaleResolver localeResolver;
/** 主题解析器;强大的主题效果更换 */
private ThemeResolver themeResolver;
/** Handler映射信息;HandlerMapping */
private List<HandlerMapping> handlerMappings;
/** Handler的适配器 */
private List<HandlerAdapter> handlerAdapters;
/** SpringMVC强大的异常解析功能;异常解析器 */
private List<HandlerExceptionResolver> handlerExceptionResolvers;
/** 请求到视图名称组件 */
private RequestToViewNameTranslator viewNameTranslator;
/** FlashMap+Manager:SpringMVC中运行重定向携带数据的功能 */
private FlashMapManager flashMapManager;
/** 视图解析器; */
private List<ViewResolver> viewResolvers;

DispatcherServlet中九大组件初始化的地方

protected void initStrategies(ApplicationContext context) {
        initMultipartResolver(context);
        initLocaleResolver(context);
        initThemeResolver(context);
        initHandlerMappings(context);
        initHandlerAdapters(context);
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }

可以在web.xml中修改DispatcherServlet某些属性的默认配置;

<init-param>
            <param-name>detectAllHandlerMappings</param-name>
            <param-value>false</param-value>
</init-param>

组件的初始化: 有些组件在容器中是使用类型找的,有些组件是使用id找的; 去容器中找这个组件,如果没有找到就用默认的配置;

初始化HandlerMapping

HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);

public String updateBook(@RequestParam(value="author")String author,Map<String, Object> model,
                      HttpServletRequest request, @ModelAttribute("haha")Book book
            )
			
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());执行目标方法的细节;
     ||
     \/
return invokeHandlerMethod(request, response, handler);
     ||
     \/
//org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#invokeHandlerMethod
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
 
//拿到方法的解析器
ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
 
//方法解析器根据当前请求地址找到真正的目标方法
Method handlerMethod = methodResolver.resolveHandlerMethod(request);
 
//创建一个方法执行器;
ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
 
//包装原生的request, response,
ServletWebRequest webRequest = new ServletWebRequest(request, response);
 
//!创建了一个,隐含模型
ExtendedModelMap implicitModel = new BindingAwareModelMap();
 
//!!真正执行目标方法;目标方法利用反射执行期间确定参数值,提前执行modelattribute等所有的操作都在这个方法中;
Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
ModelAndView mav =
		methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
return mav;
}

方法执行的细节invokeHandlerMethod

publicfinal Object invokeHandlerMethod(Method handlerMethod, Object handler,
		NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
 
//public java.lang.String com.atguigu.controller.ModelAttributeTestController.updateBook(java.lang.String,java.util.Map,javax.servlet.http.HttpServletRequest,com.atguigu.bean.Book)		
Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
try {
	boolean debug = logger.isDebugEnabled();
	for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
		Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
		if (attrValue != null) {
			implicitModel.addAttribute(attrName, attrValue);
 
		}
 
	}
	   
  //找到所有@ModelAttribute注解标注的方法;
//public void com.atguigu.controller.ModelAttributeTestController.hahaMyModelAttribute(java.util.Map,java.lang.String)
	for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
 
		Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
 
		//先确定modelattribute方法执行时要使用的每一个参数的值;
        // 隐含模型 implicitModel
        //进入这个方法
	   Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
		if (debug) {
			logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
		}
        // @ModelAttribute value 如果有值的话,返回的Mode key 就为这个值,否则是返回类型小写
		String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
		if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
			continue;
		}
 
		ReflectionUtils.makeAccessible(attributeMethodToInvoke);
	   
	   //提前运行ModelAttribute,
		Object attrValue = attributeMethodToInvoke.invoke(handler, args);
//没标:attrName="";attrName就会变为返回值类型首字母小写,比如void ,或者book;
		if ("".equals(attrName)) {
			Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
			attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
 
		}
		//把提前运行的ModelAttribute方法的返回值也放在隐含模型中
		if (!implicitModel.containsAttribute(attrName)) {
			implicitModel.addAttribute(attrName, attrValue);
		}
 
	}
 
	   //再次解析目标方法参数是哪些值
	Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
	if (debug) {
		logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
	}
 
	ReflectionUtils.makeAccessible(handlerMethodToInvoke);
 
	//执行目标方法
	return handlerMethodToInvoke.invoke(handler, args);
}
catch (IllegalStateException ex) {
	// Internal assertion failed (e.g. invalid signature):
	// throw exception with full handler method context...
	throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
}
catch (InvocationTargetException ex) {
	// User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
	ReflectionUtils.rethrowException(ex.getTargetException());
	 return null;
}
 
}

public java.lang.String com.atguigu.controller.ModelAttributeTestController.updateBook(
java.lang.String,
java.util.Map,
javax.servlet.http.HttpServletRequest,
com.atguigu.bean.Book)

private Object[] resolveHandlerArguments(Method handlerMethod, Object handler,
		NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
 
Class<?>[] paramTypes = handlerMethod.getParameterTypes();
//创建了一个和参数个数一样多的数组,会用来保存每一个参数的值
Object[] args = new Object[paramTypes.length];
 
 
			  
for (int i = 0; i < args.length; i++) {
 
MethodParameter methodParam = new MethodParameter(handlerMethod, i);
methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
String paramName = null;
String headerName = null;
boolean requestBodyFound = false;
String cookieName = null;
String pathVarName = null;
String attrName = null;
boolean required = false;
String defaultValue = null;
boolean validate = false;
Object[] validationHints = null;
int annotationsFound = 0;
Annotation[] paramAnns = methodParam.getParameterAnnotations();
 
//找到目标方法这个参数的所有注解,如果有注解就解析并保存注解的信息;
for (Annotation paramAnn : paramAnns) {
	if (RequestParam.class.isInstance(paramAnn)) {
		RequestParam requestParam = (RequestParam) paramAnn;
		paramName = requestParam.value();
		required = requestParam.required();
		defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
		annotationsFound++;
	}
	else if (RequestHeader.class.isInstance(paramAnn)) {
		RequestHeader requestHeader = (RequestHeader) paramAnn;
		headerName = requestHeader.value();
		required = requestHeader.required();
		defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());
		annotationsFound++;
	}
	else if (RequestBody.class.isInstance(paramAnn)) {
		requestBodyFound = true;
		annotationsFound++;
	}
	else if (CookieValue.class.isInstance(paramAnn)) {
		CookieValue cookieValue = (CookieValue) paramAnn;
		cookieName = cookieValue.value();
		required = cookieValue.required();
		defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue());
		annotationsFound++;
	}
	else if (PathVariable.class.isInstance(paramAnn)) {
		PathVariable pathVar = (PathVariable) paramAnn;
		pathVarName = pathVar.value();
		annotationsFound++;
	}
	else if (ModelAttribute.class.isInstance(paramAnn)) {
		ModelAttribute attr = (ModelAttribute) paramAnn;
		attrName = attr.value();
		annotationsFound++;
	}
	else if (Value.class.isInstance(paramAnn)) {
		defaultValue = ((Value) paramAnn).value();
	}
	else if (paramAnn.annotationType().getSimpleName().startsWith("Valid")) {
		validate = true;
		Object value = AnnotationUtils.getValue(paramAnn);
		validationHints = (value instanceof Object[] ? (Object[]) value : new Object[] {value});
	}
}
//前面的注解自能标注一次
if (annotationsFound > 1) {
	throw new IllegalStateException("Handler parameter annotations are exclusive choices - " +
			"do not specify more than one such annotation on the same parameter: " + handlerMethod);
}
 
 
 
//没有找到注解的情况;
if (annotationsFound == 0) {
	//解析普通参数
    //!! 确定参数是否是原生API
	Object argValue = resolveCommonArgument(methodParam, webRequest);--会进入resolveStandardArgument(解析标准参数)
	if (argValue != WebArgumentResolver.UNRESOLVED) {
		args[i] = argValue;
	}
	else if (defaultValue != null) {
		args[i] = resolveDefaultValue(defaultValue);
	}
	else {
		Class<?> paramType = methodParam.getParameterType();
		if (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) {
			if (!paramType.isAssignableFrom(implicitModel.getClass())) {
				throw new IllegalStateException("Argument [" + paramType.getSimpleName() + "] is of type " +
						"Model or Map but is not assignable from the actual model. You may need to switch " +
						"newer MVC infrastructure classes to use this argument.");
			}
    //!!! 
    // !把隐含模型(BindingAwareModelMap)复制给这个参数
    //https://blog.csdn.net/qq_40794973/article/details/97620663
    //解释为什么前面那些参数是同一个对象的原因
			args[i] = implicitModel;
		}
		else if (SessionStatus.class.isAssignableFrom(paramType)) {
			args[i] = this.sessionStatus;
		}
		else if (HttpEntity.class.isAssignableFrom(paramType)) {
			args[i] = resolveHttpEntityRequest(methodParam, webRequest);
		}
		else if (Errors.class.isAssignableFrom(paramType)) {
			throw new IllegalStateException("Errors/BindingResult argument declared " +
					"without preceding model attribute. Check your handler method signature!");
		}
		else if (BeanUtils.isSimpleProperty(paramType)) {
			paramName = "";
		}
		else {
			attrName = "";
		}
	}
}
 
 
 
//确定值的环节
if (paramName != null) {
    //进入  String[] paramValues = webRequest.getParameterValues(paramName);
	args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);
}
else if (headerName != null) {
	args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);
}
else if (requestBodyFound) {
	args[i] = resolveRequestBody(methodParam, webRequest, handler);
}
else if (cookieName != null) {
	args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);
}
else if (pathVarName != null) {
	args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);
 
}
 
//确定自定义类型参数的值;还要将请求中的每一个参数赋值给这个对象
else if (attrName != null) {
	WebDataBinder binder =
			resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
	boolean assignBindingResult = (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
	if (binder.getTarget() != null) {
		doBind(binder, webRequest, validate, validationHints, !assignBindingResult);
	}
	args[i] = binder.getTarget();
	if (assignBindingResult) {
		args[i + 1] = binder.getBindingResult();
		i++;
	}
	implicitModel.putAll(binder.getBindingResult().getModel());
}
 
}
	return args;
 
}

如果没有注解: 1)、先看是否普通参数(resolveCommonArgument);----就是确定当前的参数是否是原生API;

@Override
protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest) throws Exception {
	HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
	HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
 
	if (ServletRequest.class.isAssignableFrom(parameterType) ||
			MultipartRequest.class.isAssignableFrom(parameterType)) {
		Object nativeRequest = webRequest.getNativeRequest(parameterType);
		if (nativeRequest == null) {
			throw new IllegalStateException(
					"Current request is not of type [" + parameterType.getName() + "]: " + request);
		}
		return nativeRequest;
	}
	else if (ServletResponse.class.isAssignableFrom(parameterType)) {
		this.responseArgumentUsed = true;
		Object nativeResponse = webRequest.getNativeResponse(parameterType);
		if (nativeResponse == null) {
			throw new IllegalStateException(
					"Current response is not of type [" + parameterType.getName() + "]: " + response);
		}
		return nativeResponse;
	}
	else if (HttpSession.class.isAssignableFrom(parameterType)) {
		return request.getSession();
	}
	else if (Principal.class.isAssignableFrom(parameterType)) {
		return request.getUserPrincipal();
	}
	else if (Locale.class.equals(parameterType)) {
		return RequestContextUtils.getLocale(request);
	}
	else if (InputStream.class.isAssignableFrom(parameterType)) {
		return request.getInputStream();
	}
	else if (Reader.class.isAssignableFrom(parameterType)) {
		return request.getReader();
	}
	else if (OutputStream.class.isAssignableFrom(parameterType)) {
		this.responseArgumentUsed = true;
		return response.getOutputStream();
	}
	else if (Writer.class.isAssignableFrom(parameterType)) {
		this.responseArgumentUsed = true;
		return response.getWriter();
	}
	return super.resolveStandardArgument(parameterType, webRequest);
}

2)、判断是否是Model或者是Map旗下的,如果是将之前创建的隐含模型直接赋值给这个参数;

方法上标注的ModelAttribute注解如果有value值

@ModelAttribute("abc")

hahaMyModelAttribute()

    标了 :  attrName="abc"

    没标:attrName="";attrName就会变为返回值类型首字母小写,比如void ,或者book;

【@ModelAttribute标在方法上的另外一个作用;

可以把方法运行后的返回值按照方法上@ModelAttribute("abc")指定的key放到隐含模型中;

如果没有指定这个key;就用返回值类型的首字母小写】

{haha=Book [id=100, bookName=西游记, author=吴承恩, stock=98, sales=10, price=98.98], void=null}

@ModelAttribute("haha")Book book

标了注解: 保存时哪个注解的详细信息; 如果参数有ModelAttribute注解; 拿到ModelAttribute注解的值让attrName保存 attrName="haha"

没标注解: 1)、先看是否普通参数(是否原生API) 再看是否Model或者Map,如果是就传入隐含模型; 2)、自定义类型的参数没有ModelAttribute 注解 1)、先看是否原生API 2)、再看是否Model或者Map 3)、再看是否是其他类型的比如SessionStatus、HttpEntity、Errors 4)、再看是否简单类型的属性;比如是否Integer,String,基本类型 如果是paramName=“” 5)、attrName=""; 如果是自定义类型对象,最终会产生两个效果; 1)、如果这个参数标注了ModelAttribute注解就给attrName赋值为这个注解的value值 2)、如果这个参数没有标注ModelAttribute注解就给attrName赋值"";

###确定自定义类型参数的值

private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam,
            ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception {
 
        // Bind request parameter onto object...  
        String name = attrName;
     
        if ("".equals(name)) {
               //如果attrName是空串;就将参数类型的首字母小写作为值  Book book2121;name=book
            name = Conventions.getVariableNameForParameter(methodParam);
        }
        Class<?> paramType = methodParam.getParameterType();
        Object bindObject;确定目标对象的值
        if (implicitModel.containsKey(name)) {
            bindObject = implicitModel.get(name);
        }
        else if (this.methodResolver.isSessionAttribute(name, paramType)) {
            bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
            if (bindObject == null) {
                raiseSessionRequiredException("Session attribute '" + name + "' required - not found in session");
            }
        }
        else {
            bindObject = BeanUtils.instantiateClass(paramType);
        }
        WebDataBinder binder = createBinder(webRequest, bindObject, name);
        initBinder(handler, name, binder, webRequest);
        return binder;
    }

SpringMVC确定POJO值的三步;

1、如果隐含模型中有这个key(标了ModelAttribute注解就是注解指定的value,没标就是参数类型的首字母小写)指定的值;

      如果有将这个值赋值给bindObject;

2、如果是SessionAttributes标注的属性,就从session中拿;

3、如果都不是就利用反射创建对象; 两件事: 1)、运行流程简单版; 2)、确定方法每个参数的值; 1)、标注解:保存注解的信息;最终得到这个注解应该对应解析的值; 2)、没标注解: 1)、看是否是原生API; 2)、看是否是Model或者是Map,xxxx 3)、都不是,看是否是简单类型;paramName; 4)、给attrName赋值;attrName(参数标了@ModelAttribute("")就是指定的,没标就是"") 确定自定义类型参数: 1)、attrName使用参数的类型首字母小写;或者使用之前@ModelAttribute("")的值 2)、先看隐含模型中有每个这个attrName作为key对应的值;如果有就从隐含模型中获取并赋值 3)、看是否是@SessionAttributes(value="haha");标注的属性,如果是从session中拿; 如果拿不到就会抛异常; 4)、不是@SessionAttributes标注的,利用反射创建一个对象; 5)、拿到之前创建好的对象,使用数据绑定器(WebDataBinder)将请求中的每个数据绑定到这个对象中;

//确定值的环节
if (paramName != null) {
	args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);
}
else if (headerName != null) {
	args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);
}
else if (requestBodyFound) {
	args[i] = resolveRequestBody(methodParam, webRequest, handler);
}
else if (cookieName != null) {
	args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);
}
else if (pathVarName != null) {
	args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);
}
 
   //确定自定义类型参数的值;还要将请求中的每一个参数赋值给这个对象
else if (attrName != null) {
	WebDataBinder binder =
			resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
	boolean assignBindingResult = (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
	if (binder.getTarget() != null) {
		doBind(binder, webRequest, validate, validationHints, !assignBindingResult);
	}
	args[i] = binder.getTarget();
	if (assignBindingResult) {
		args[i + 1] = binder.getBindingResult();
		i++;
	}
	implicitModel.putAll(binder.getBindingResult().getModel());
}
}
return args;

https://www.bilibili.com/video/BV1uE411C7CW?p=156

标签:null,SpringMvc,handler,args,else,attrName,webRequest,原理,解析
From: https://blog.51cto.com/u_15993308/6207498

相关文章

  • admin项目公共方法解析
    前言:项目中公用的一些方法,配置,常量等正文:文件:common/inc.go packagecommonconstTimeTem="2006-01-0215:04:05"constAdminSecret="jO4s4QcGs4B8brP2"//随机秘钥//定义一个统一的返回对象typeReDatastruct{StatusboolMsgstringData......
  • 高斯混合模型疑点解析
    高斯混合模型是EM算法的优秀实践,表达形式也十分简单,但是其推导确实有点复杂。推荐几篇不错的文章:(26条消息)ML-朴素贝叶斯-先验分布/后验分布/似然估计_特征条件独立性假设_透明的胡萝卜的博客-CSDN博客 (此篇文章介绍了一些朴素贝叶斯基本知识,建议先看)高斯混合模型(GMM)推导及......
  • 图数据库 NebulaGraph 的 Java 数据解析实践与指导
    如何快速、即时、符合直觉地去处理NebulaJavaClient中的数据解析?读这一篇就够了。图数据库NebulaGrpah的论坛和微信群里,有不少用户问及了Java客户端数据解析的问题。在本文教你一种简单的方式同返回结果交互,快速、即时地拿到解析数据。愉快、干净的Java交互环境本......
  • javasec(四)序列化与反序列化基本原理
    title:javasec(四)序列化与反序列化基本原理tags:-javasec-反序列化categories:-javaseccover:'https://blog-1313934826.cos.ap-chengdu.myqcloud.com/blog-images/1.jpeg'feature:falsedate:2023-04-1816:02:20这篇文章介绍java序列化与反序列化基本原......
  • 推排序 Verilog实现原理
    引言推排序常常应用在操作系统的任务调度中,尝试使用硬件对堆排序进行实现,在实现的过程中不使用function和tasks语法,即真·硬件实现参考的博客也就这一个博客有介绍堆排序的Verilog实现原理堆排序还需要复习一遍吗?我肯定是要的菜鸟-堆排序图解排序算法(三)之堆排序可以......
  • MongoDB 4.2:配置文件选项全解析《二》
    1.net.unixDomainSocket选项net:unixDomainSocket:enabled:<boolean>pathPrefix:<string>filePermissions:<int>net.unixDomainSocket.enabledType:boolean默认值:True启用或禁用UNIX域套接字上的侦听。net.unixDomainSocket.enabled仅适用于基于Uni......
  • 动态拨号代理池的应用场景与实现原理解析
    随着互联网的发展和应用场景的不断扩大,数据采集和爬虫技术也日渐成为一项重要的任务。然而,很多网站为了保护自身权益,设置了严格的反爬虫策略,让数据采集变得更加困难。在这种情况下,动态拨号代理池成为了解决方案之一。动态拨号代理池的应用场景动态拨号代理池主要在以下几方......
  • 计算机组成原理
    计算机组成原理第二章计算机系统中的数据表示一)数值数据的编码1、补码1)补码概念引入2)补码的定义计算机中的浮点数是以纯小数和纯整数部分构成的,所以要表示一个浮点数只需要知道它的小数部分和整数部分怎么表示。n位二进制纯小数的编码由一位整数位(也是符号位),和n-1位小......
  • MYSQL索引失效场景及其原理
    MySQL索引失效是指查询时不能有效利用索引,从而导致查询性能下降的现象。以下是一些常见的MySQL索引失效场景及原理:使用函数或表达式:在WHERE子句中对索引列使用函数或表达式会导致索引失效。因为MySQL无法预先计算表达式的结果,所以无法使用索引进行查找。例:SELECT*FROMusersWH......
  • MySQL事务实现原理
    事务是什么?首先思考一个问题,事务是什么?以下是事务的相关解释MySQL中的事务是一种用于确保数据库操作的完整性和一致性的机制。事务处理具有以下四个基本特性,通常被称为ACID特性:原子性(Atomicity):原子性是指事务中的所有操作要么全部完成,要么全部不完成。事务中的操作不可分割,如果......