yolov3之pytorch源码解析_springmvc源码架构解析之view

说在前面

前期回顾

sharding-jdbc源码解析 更新完毕

spring源码解析 更新完毕

spring-mvc源码解析 更新完毕

spring-tx源码解析 更新完毕

spring-boot源码解析 更新完毕

rocketmq源码解析 更新完毕

dubbbo源码解析 更新完毕

netty源码解析 更新完毕

spring源码架构更新完毕

springmvc源码架构更新中

springboot源码架构计划中

github https://github.com/tianheframe

sharding-jdbc源码解析 更新完毕

rocketmq源码解析 更新完毕

seata 源码解析 更新完毕

dubbo 源码解析 更新完毕

netty 源码解析 更新完毕

源码解析

58a1997d5476e05152cabe30062fb139.png

org.springframework.web.servlet.View 用于web交互的MVC视图。实现负责呈现内容和公开模型。单个视图公开多个模型属性。这个类和与之相关的MVC方法在Rod Johnson (Wrox, 2002)的专家一对一J2EE设计和开发的第12章中进行了讨论。视图实现可能差别很大。一个明显的实现是基于jsp的。其他实现可能是基于xsl的,或者使用HTML生成库。此接口旨在避免限制可能实现的范围。视图应该是bean。它们很可能被视图解析器实例化为bean。由于这个接口是无状态的,所以视图实现应该是线程安全的。

  String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";

包含响应状态代码的HttpServletRequest属性的名称。注意:并非所有视图实现都支持此属性。

  String PATH_VARIABLES = View.class.getName() + ".pathVariables";

HttpServletRequest属性的名称,该属性包含带有路径变量的映射。映射由基于字符串的URI模板变量名作为键及其对应的基于对象的值组成——从URL的片段中提取并转换类型。注意:并非所有视图实现都支持此属性。

  String SELECTED_CONTENT_TYPE = View.class.getName() + ".selectedContentType";

在内容协商期间选择的MediaType,它可能比视图配置的MediaType更具体。例如:“应用程序/盾。example-v1 + xml”和“应用程序/ * + xml”。

  String getContentType();

如果预先确定,返回视图的内容类型。可用于提前检查视图的内容类型,即在实际呈现尝试之前。

  void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;

呈现给定指定模型的视图。第一步是准备请求:在JSP中,这意味着将模型对象设置为请求属性。第二步是视图的实际呈现,例如通过RequestDispatcher包含JSP。

org.springframework.web.servlet.SmartView 提供关于视图的附加信息,如视图是否执行重定向。

  boolean isRedirectView();

是否是重定向视图

org.springframework.web.servlet.view.AbstractView 视图实现的抽象基类。子类应该是javabean,以便作为spring管理的bean实例进行方便的配置。

提供对视图可用的静态属性的支持,并提供多种方法来指定它们。静态属性将与每个呈现操作的给定动态属性(控制器返回的模型)合并。扩展WebApplicationObjectSupport,这将对某些视图有帮助。子类只需要实现实际的呈现。

  public static final String DEFAULT_CONTENT_TYPE = "text/html;charset=ISO-8859-1";

默认contentType

  private static final int OUTPUT_BYTE_ARRAY_INITIAL_SIZE = 4096;

初始化输出数组大小

public void setExposeContextBeansAsAttributes(boolean exposeContextBeansAsAttributes) {    this.exposeContextBeansAsAttributes = exposeContextBeansAsAttributes;  }

设置是否让应用程序上下文中的所有Spring bean都可以作为请求属性进行访问,方法是在属性被访问后进行惰性检查。这将使所有此类bean在普通${…}表达式,以及JSTL的c:out值表达式。默认设置是“假”。打开此标志以透明地公开request属性名称空间中的所有Spring bean。注意:上下文bean将覆盖手动添加的任何相同名称的自定义请求或会话属性。然而,相同名称的模型属性(如显式地公开给这个视图)总是会覆盖上下文bean。

public void setExposedContextBeanNames(String... exposedContextBeanNames) {    this.exposedContextBeanNames = new HashSet<String>(Arrays.asList(exposedContextBeanNames));  }

指定应该公开的上下文中bean的名称。如果这是非空的,只有指定的bean才有资格作为属性公开。如果您想在应用程序上下文中公开所有Spring bean,请打开“exposeContextBeansAsAttributes”标志,但不要为此属性列出特定的bean名称。

@Override  public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {    if (logger.isTraceEnabled()) {      logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +        " and static attributes " + this.staticAttributes);    }    Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);    prepareResponse(request, response);    renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);  }

准备给定指定模型的视图,必要时将其与静态属性和RequestContext属性合并。将实际呈现委托给renderMergedOutputModel。这里是模板方法实现

org.springframework.web.servlet.view.AbstractView#createMergedOutputModel 创建包含动态值和静态属性的组合输出映射(从不为空)。动态值优先于静态属性。

protected Map<String, Object> createMergedOutputModel(Map<String, ?> model, HttpServletRequest request,      HttpServletResponse response) {    @SuppressWarnings("unchecked")    Map<String, Object> pathVars = (this.exposePathVariables ?        (Map<String, Object>) request.getAttribute(View.PATH_VARIABLES) : null);    // Consolidate static and dynamic model attributes.    int size = this.staticAttributes.size();    size += (model != null ? model.size() : 0);    size += (pathVars != null ? pathVars.size() : 0);    Map<String, Object> mergedModel = new LinkedHashMap<String, Object>(size);    mergedModel.putAll(this.staticAttributes);    if (pathVars != null) {      mergedModel.putAll(pathVars);    }    if (model != null) {      mergedModel.putAll(model);    }    // Expose RequestContext?    if (this.requestContextAttribute != null) {      mergedModel.put(this.requestContextAttribute, createRequestContext(request, response, mergedModel));    }    return mergedModel;  }

org.springframework.web.servlet.view.AbstractView#createRequestContext 创建一个RequestContext,在指定的属性名下公开。默认实现为给定的请求和模型创建一个标准的RequestContext实例。可在自定义实例的子类中重写。

protected RequestContext createRequestContext(      HttpServletRequest request, HttpServletResponse response, Map<String, Object> model) {    return new RequestContext(request, response, getServletContext(), model);  }

org.springframework.web.servlet.view.AbstractView#prepareResponse 为呈现准备给定的响应。默认的实现在通过HTTPS发送下载内容时应用了IE bug的解决方案。

protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) {    if (generatesDownloadContent()) {      response.setHeader("Pragma", "private");      response.setHeader("Cache-Control", "private, must-revalidate");    }  }

org.springframework.web.servlet.view.AbstractView#generatesDownloadContent 返回该视图是否生成下载内容(通常是PDF或Excel文件等二进制内容)。默认实现返回false。如果子类知道在客户端生成需要临时缓存的下载内容(通常是通过响应OutputStream),那么在这里鼓励它们返回true。

org.springframework.web.servlet.view.AbstractView#renderMergedOutputModel 子类必须实现这个方法来实际呈现视图。第一步是准备请求:在JSP中,这意味着将模型对象设置为请求属性。第二步是视图的实际呈现,例如通过RequestDispatcher包含JSP。

org.springframework.web.servlet.view.AbstractView#exposeModelAsRequestAttributes 将给定映射中的模型对象公开为请求属性。名称将取自模型映射。此方法适用于javax.servlet.RequestDispatcher可访问的所有资源。

  protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {    for (Map.Entry<String, Object> entry : model.entrySet()) {      String modelName = entry.getKey();      Object modelValue = entry.getValue();      if (modelValue != null) {        request.setAttribute(modelName, modelValue);        if (logger.isDebugEnabled()) {          logger.debug("Added model object '" + modelName + "' of type [" + modelValue.getClass().getName() +              "] to request in view with name '" + getBeanName() + "'");        }      }      else {        request.removeAttribute(modelName);        if (logger.isDebugEnabled()) {          logger.debug("Removed model object '" + modelName +              "' from request in view with name '" + getBeanName() + "'");        }      }    }  }
protected ByteArrayOutputStream createTemporaryOutputStream() {    return new ByteArrayOutputStream(OUTPUT_BYTE_ARRAY_INITIAL_SIZE);  }

为这个视图创建一个临时输出流。这通常用作IE解决方案,用于在实际将内容写入HTTP响应之前设置临时流的内容长度标头。

protected void writeToResponse(HttpServletResponse response, ByteArrayOutputStream baos) throws IOException {    // Write content type and also length (determined via byte array).    response.setContentType(getContentType());    response.setContentLength(baos.size());    // Flush byte array to servlet output stream.    ServletOutputStream out = response.getOutputStream();    baos.writeTo(out);    out.flush();  }

将给定的临时输出流写入HTTP响应。

protected void setResponseContentType(HttpServletRequest request, HttpServletResponse response) {    MediaType mediaType = (MediaType) request.getAttribute(View.SELECTED_CONTENT_TYPE);    if (mediaType != null && mediaType.isConcrete()) {      response.setContentType(mediaType.toString());    }    else {      response.setContentType(getContentType());    }  }

设置响应到配置的内容类型的内容类型,除非视图。出现SELECTED_CONTENT_TYPE请求属性,并将其设置为具体的媒体类型。

org.springframework.web.servlet.view.AbstractUrlBasedView 基于url视图的抽象基类。提供以“URL”bean属性的形式保存视图包装的URL的一致方式。

private String url;

url

@Override  public void afterPropertiesSet() throws Exception {    if (isUrlRequired() && getUrl() == null) {      throw new IllegalArgumentException("Property 'url' is required");    }  }

校验url

org.springframework.web.servlet.view.RedirectView 重定向到绝对URL、上下文相对URL或当前请求相对URL的视图。URL可能是URI模板,在这种情况下,URI模板变量将被模型中可用的值替换。默认情况下,所有基本模型属性(或其集合)都作为HTTP查询参数公开(假设它们没有用作URI模板变量),但是可以通过覆盖isEligibleProperty(String, Object)方法来更改这种行为。这个视图的URL应该是一个HTTP重定向URL,即适合HttpServletResponse的sendRedirect方法,如果HTTP 1.0标志是打开的,或者通过发送一个HTTP 303代码(如果HTTP 1.0兼容标志是关闭的)来重定向。注意,虽然“contextRelative”标志的默认值为off,但您可能希望几乎总是将其设置为true。当标志关闭时,以“/”开头的url被认为是相对于web服务器根的,而当标志打开时,它们被认为是相对于web应用程序根的。由于大多数web应用程序永远不会知道或关心它们的上下文路径实际上是什么,因此最好将此标志设置为true,并提交相对于web应用程序根目录的路径。在Portlet环境中使用此重定向视图时请注意:确保您的控制器遵守Portlet sendRedirect约束。

public void setExposePathVariables(boolean exposePathVariables) {    this.exposePathVariables = exposePathVariables;  }

指定是否向模型中添加路径变量。路径变量通常通过@PathVariable注释绑定到URI模板变量。它们实际上是URI模板变量,类型转换应用于它们以派生类型化的对象值。视图中经常需要这些值来构造指向相同url和其他url的链接。添加到模型中的路径变量覆盖静态属性(参见setAttributes(Properties)),但不覆盖模型中已经存在的属性。默认情况下,此标志设置为true。具体的视图类型可以覆盖它。

public void setContextRelative(boolean contextRelative) {    this.contextRelative = contextRelative;  }

设置是否将以斜杠("/")开头的给定URL解释为相对于当前ServletContext,即相对于web应用程序根目录的URL。默认值是“false”:以斜杠开头的URL将被解释为绝对的,即按原样接受。如果“true”,在这种情况下,上下文路径将在URL之前。

public void setHttp10Compatible(boolean http10Compatible) {    this.http10Compatible = http10Compatible;  }

sendRedirect设置是否与HTTP 1.0客户端保持兼容。在默认实现中,这将在任何情况下强制执行HTTP状态码302,即委托给HttpServletResponse.sendRedirect。关闭此选项将发送HTTP状态代码303,这是HTTP 1.1客户端的正确代码,但HTTP 1.0客户端不能理解。许多HTTP 1.1客户端对待302就像对待303一样,没有任何区别。但是,有些客户端在POST请求后重定向时依赖于303;在这种情况下,关闭此标志。

public void setExposeModelAttributes(final boolean exposeModelAttributes) {    this.exposeModelAttributes = exposeModelAttributes;  }

设置说明文属性标志,它表示模型属性是否应该作为HTTP查询参数公开。默认值为true。

public void setExpandUriTemplateVariables(boolean expandUriTemplateVariables) {    this.expandUriTemplateVariables = expandUriTemplateVariables;  }

是否将重定向URL视为URI模板。如果重定向URL包含左花括号“{”和右花括号“}”,并且不希望它们被解释为URI变量,则将此标志设置为false。默认值为true。

public void setPropagateQueryParams(boolean propagateQueryParams) {    this.propagateQueryParams = propagateQueryParams;  }

当设置为true时,将追加当前URL的查询字符串,从而传播到重定向的URL。默认值为false。

@Override  public boolean isRedirectView() {    return true;  }

返回“true”,指示此视图执行重定向。

@Override  protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,      HttpServletResponse response) throws IOException {//    创建url    String targetUrl = createTargetUrl(model, request);//    更新url    targetUrl = updateTargetUrl(targetUrl, model, request, response);    FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);    if (!CollectionUtils.isEmpty(flashMap)) {      UriComponents uriComponents = UriComponentsBuilder.fromUriString(targetUrl).build();      flashMap.setTargetRequestPath(uriComponents.getPath());      flashMap.addTargetRequestParams(uriComponents.getQueryParams());      FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request);      if (flashMapManager == null) {        throw new IllegalStateException("FlashMapManager not found despite output FlashMap having been set");      }      flashMapManager.saveOutputFlashMap(flashMap, request, response);    }//    重定向    sendRedirect(request, response, targetUrl, this.http10Compatible);  }

将模型转换为请求参数并重定向到给定的URL。

org.springframework.web.servlet.view.RedirectView#createTargetUrl 首先检查重定向字符串是否是URI模板,然后使用给定的模型展开它,然后可选地添加简单类型模型属性作为查询字符串参数,从而创建目标URL。

  protected final String createTargetUrl(Map<String, Object> model, HttpServletRequest request)      throws UnsupportedEncodingException {    // Prepare target URL.    StringBuilder targetUrl = new StringBuilder();    if (this.contextRelative && getUrl().startsWith("/")) {      // Do not apply context path to relative URLs.      targetUrl.append(getContextPath(request));    }    targetUrl.append(getUrl());    String enc = this.encodingScheme;    if (enc == null) {      enc = request.getCharacterEncoding();    }    if (enc == null) {      enc = WebUtils.DEFAULT_CHARACTER_ENCODING;    }    if (this.expandUriTemplateVariables && StringUtils.hasText(targetUrl)) {      Map<String, String> variables = getCurrentRequestUriVariables(request);      targetUrl = replaceUriTemplateVariables(targetUrl.toString(), model, variables, enc);    }    if (isPropagateQueryProperties()) {       appendCurrentQueryParams(targetUrl, request);    }    if (this.exposeModelAttributes) {      appendQueryProperties(targetUrl, model, enc);    }    return targetUrl.toString();  }

org.springframework.web.servlet.view.RedirectView#updateTargetUrl 找到注册的RequestDataValueProcessor(如果有的话),并允许它更新重定向目标URL。

protected String updateTargetUrl(String targetUrl, Map<String, Object> model,      HttpServletRequest request, HttpServletResponse response) {    WebApplicationContext wac = getWebApplicationContext();    if (wac == null) {      wac = RequestContextUtils.findWebApplicationContext(request, getServletContext());    }    if (wac != null && wac.containsBean(RequestContextUtils.REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME)) {      RequestDataValueProcessor processor = wac.getBean(          RequestContextUtils.REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME, RequestDataValueProcessor.class);      return processor.processUrl(request, targetUrl);    }    return targetUrl;  }

org.springframework.web.servlet.view.RedirectView#sendRedirect 将重定向发送回HTTP客户机

protected void sendRedirect(HttpServletRequest request, HttpServletResponse response,      String targetUrl, boolean http10Compatible) throws IOException {    String encodedURL = (isRemoteHost(targetUrl) ? targetUrl : response.encodeRedirectURL(targetUrl));    if (http10Compatible) {      HttpStatus attributeStatusCode = (HttpStatus) request.getAttribute(View.RESPONSE_STATUS_ATTRIBUTE);      if (this.statusCode != null) {        response.setStatus(this.statusCode.value());        response.setHeader("Location", encodedURL);      }      else if (attributeStatusCode != null) {        response.setStatus(attributeStatusCode.value());        response.setHeader("Location", encodedURL);      }      else {        // Send status code 302 by default. 执行response.sendRedirect重定向        response.sendRedirect(encodedURL);      }    }    else {      HttpStatus statusCode = getHttp11StatusCode(request, response, targetUrl);      response.setStatus(statusCode.value());      response.setHeader("Location", encodedURL);    }  }

org.springframework.web.servlet.view.document.AbstractPdfStamperView 抽象超类,用于对具有AcroForm的现有文档进行操作的PDF视图。特定于应用程序的视图类将扩展这个类以合并PDF表单和模型数据。这个视图实现使用Bruno Lowagie的iText API。已知可以使用原始的iText 2.1.7及其分支OpenPDF。我们强烈推荐OpenPDF,因为它是积极维护的,并且修复了不可信PDF内容的一个重要漏洞。

public AbstractPdfStamperView(){    setContentType("application/pdf");  }

创建AbstractPdfStamperView,设置contentType=application/pdf

@Override  protected final void renderMergedOutputModel(      Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {    // IE workaround: write into byte array first.创建输出流    ByteArrayOutputStream baos = createTemporaryOutputStream();    PdfReader reader = readPdfResource();    PdfStamper stamper = new PdfStamper(reader, baos);//    模板方法    mergePdfDocument(model, stamper, request, response);    stamper.close();    // Flush to HTTP response.    writeToResponse(response, baos);  }

渲染输出model

org.springframework.web.servlet.view.AbstractView#createTemporaryOutputStream 为这个视图创建一个临时输出流。这通常用作IE解决方案,用于在实际将内容写入HTTP响应之前设置临时流的内容长度标头。

protected ByteArrayOutputStream createTemporaryOutputStream() {    return new ByteArrayOutputStream(OUTPUT_BYTE_ARRAY_INITIAL_SIZE);  }

org.springframework.web.servlet.view.document.AbstractPdfStamperView#mergePdfDocument 子类必须实现此方法来将PDF表单与给定的模型数据合并。这是您可以在AcroForm上设置值的地方。在这一级可以做的一个例子是:请注意,传入的HTTP响应只用于设置cookie或其他HTTP报头。在此方法返回后,构建的PDF文档本身将自动写入响应。

protected abstract void mergePdfDocument(Map<String, Object> model, PdfStamper stamper,      HttpServletRequest request, HttpServletResponse response) throws Exception;

org.springframework.web.servlet.view.AbstractView#writeToResponse 将给定的临时输出流写入HTTP响应。

protected void writeToResponse(HttpServletResponse response, ByteArrayOutputStream baos) throws IOException {    // Write content type and also length (determined via byte array).    response.setContentType(getContentType());    response.setContentLength(baos.size());    // Flush byte array to servlet output stream.    ServletOutputStream out = response.getOutputStream();    baos.writeTo(out);    out.flush();  }

org.springframework.web.servlet.view.InternalResourceView 同一web应用程序中JSP或其他资源的包装器。将模型对象公开为请求属性,并使用RequestDispatcher将请求转发到指定的资源URL。这个视图的URL应该指定web应用程序中的一个资源,该资源适合RequestDispatcher的转发或包含方法。

如果在已包含的请求或已提交的响应中操作,该视图将退回到包含而不是转发。这可以通过在呈现视图之前调用response. flushbuffer()(它将提交响应)来实现。

public void setAlwaysInclude(boolean alwaysInclude) {        this.alwaysInclude = alwaysInclude;    }

指定是否总是包含视图而不是转发视图。默认设置是“假”。打开此标志以强制使用Servlet include,即使可能使用转发。

public void setPreventDispatchLoop(boolean preventDispatchLoop) {        this.preventDispatchLoop = preventDispatchLoop;    }

设置是否显式防止分派回当前处理程序路径。默认设置是“假”。对于基于约定的视图,将其切换为“true”,其中将分派回当前处理程序路径是一个确定的错误。

@Override    protected void renderMergedOutputModel(            Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {        // Expose the model object as request attributes.将模型对象公开为请求属性。        exposeModelAsRequestAttributes(model, request);        // Expose helpers as request attributes, if any.将帮助程序公开为请求属性(如果有的话)。模板方法        exposeHelpers(request);        // Determine the path for the request dispatcher.确定请求分配器的路径。        String dispatcherPath = prepareForRendering(request, response);        // Obtain a RequestDispatcher for the target resource (typically a JSP). 获取请求转发器        RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);        if (rd == null) {            throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +                    "]: Check that the corresponding file exists within your web application archive!");        }        // If already included or response already committed, perform include, else forward. 如果include请求就执行,否则就转发        if (useInclude(request, response)) {            response.setContentType(getContentType());            if (logger.isDebugEnabled()) {                logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");            }//          执行include            rd.include(request, response);        }        else {            // Note: The forwarded resource is supposed to determine the content type itself.注意:转发的资源应该确定内容类型本身。            if (logger.isDebugEnabled()) {                logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");            }//          执行转发            rd.forward(request, response);        }    }

根据指定的模型呈现内部资源。这包括将模型设置为请求属性。这里是模板方法实现,如果inlude请求执行include请求,如果是forward执行请求转发

org.springframework.web.servlet.view.AbstractView#exposeModelAsRequestAttributes 将给定映射中的模型对象公开为请求属性。名称将取自模型映射。此方法适用于javax.servlet.RequestDispatcher可访问的所有资源。

  protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {        for (Map.Entry<String, Object> entry : model.entrySet()) {            String modelName = entry.getKey();            Object modelValue = entry.getValue();            if (modelValue != null) {                request.setAttribute(modelName, modelValue);                if (logger.isDebugEnabled()) {                    logger.debug("Added model object '" + modelName + "' of type [" + modelValue.getClass().getName() +                            "] to request in view with name '" + getBeanName() + "'");                }            }            else {                request.removeAttribute(modelName);                if (logger.isDebugEnabled()) {                    logger.debug("Removed model object '" + modelName +                            "' from request in view with name '" + getBeanName() + "'");                }            }        }    }

org.springframework.web.servlet.view.InternalResourceView#exposeHelpers 公开每个呈现操作唯一的助手。这是必要的,这样不同的呈现操作就不会覆盖彼此的上下文等等。由renderMergedOutputModel(Map, HttpServletRequest, HttpServletResponse)调用。默认实现为空。可以重写此方法,以将自定义助手添加为请求属性。

protected void exposeHelpers(HttpServletRequest request) throws Exception {    }

org.springframework.web.servlet.view.InternalResourceView#prepareForRendering 准备呈现,并确定转发(或包含)的请求分派器路径。此实现仅返回配置的URL。子类可以覆盖它以确定要呈现的资源,通常以不同的方式解释URL。

protected String prepareForRendering(HttpServletRequest request, HttpServletResponse response)            throws Exception {        String path = getUrl();        if (this.preventDispatchLoop) {            String uri = request.getRequestURI();            if (path.startsWith("/") ? uri.equals(path) : uri.equals(StringUtils.applyRelativePath(uri, path))) {                throw new ServletException("Circular view path [" + path + "]: would dispatch back " +                        "to the current handler URL [" + uri + "] again. Check your ViewResolver setup! " +                        "(Hint: This may be the result of an unspecified view, due to default view name generation.)");            }        }        return path;    }

org.springframework.web.servlet.view.InternalResourceView#getRequestDispatcher 获取用于转发/包含的RequestDispatcher。默认实现只是调用HttpServletRequest.getRequestDispatcher(字符串)。可以在子类中重写。

protected RequestDispatcher getRequestDispatcher(HttpServletRequest request, String path) {        return request.getRequestDispatcher(path);    }
protected boolean useInclude(HttpServletRequest request, HttpServletResponse response) {        return (this.alwaysInclude || WebUtils.isIncludeRequest(request) || response.isCommitted());    }

确定是使用RequestDispatcher的include方法还是转发方法。执行检查请求中是否找到包含URI属性,指示包含请求,以及响应是否已经提交。在这两种情况下,都将执行include,因为转发不再可能。

org.springframework.web.util.WebUtils#isIncludeRequest 确定给定的请求是否是包含请求,即不是来自外部的顶级HTTP请求。检查“javax.servlet.include”的存在。request_uri”请求属性。可以检查仅出现在包含请求中的任何请求属性。

public static boolean isIncludeRequest(ServletRequest request) {    return (request.getAttribute(INCLUDE_REQUEST_URI_ATTRIBUTE) != null);  }

org.springframework.web.servlet.view.JstlView JSTL页面的InternalResourceView的专门化,即使用JSP标准标记库的JSP页面。使用Spring的区域设置和MessageSource公开特定于JSTL的请求属性,这些属性指定JSTL的格式化和消息标记的区域设置和资源包。

org.springframework.web.servlet.view.AbstractTemplateView 用于基于模板的视图技术(如Velocity和FreeMarker)的适配器基类,可以在模型中使用请求和会话属性,还可以为Spring的Velocity/FreeMarker宏库公开助手对象。JSP/JSTL和其他视图技术自动访问HttpServletRequest对象,从而访问当前用户的请求/会话属性。此外,它们还能够创建帮助对象并将其缓存为请求属性本身。

public void setExposeRequestAttributes(boolean exposeRequestAttributes) {    this.exposeRequestAttributes = exposeRequestAttributes;  }

设置是否应该在与模板合并之前将所有请求属性添加到模型中。默认设置是“假”。

public void setAllowRequestOverride(boolean allowRequestOverride) {    this.allowRequestOverride = allowRequestOverride;  }

设置是否允许HttpServletRequest属性覆盖(隐藏)控制器生成的同名模型属性。默认值是“false”,如果发现与模型属性同名的请求属性,将引发异常。

public void setExposeSessionAttributes(boolean exposeSessionAttributes) {    this.exposeSessionAttributes = exposeSessionAttributes;  }

设置是否应该在与模板合并之前将所有HttpSession属性添加到模型中。默认设置是“假”

public void setAllowSessionOverride(boolean allowSessionOverride) {    this.allowSessionOverride = allowSessionOverride;  }

设置是否允许HttpSession属性覆盖(隐藏)控制器生成的同名模型属性。默认值是“false”,如果发现与模型属性同名的会话属性,将引发异常。

public void setExposeSpringMacroHelpers(boolean exposeSpringMacroHelpers) {    this.exposeSpringMacroHelpers = exposeSpringMacroHelpers;  }

设置是否以“springMacroRequestContext”的名称公开一个RequestContext以供Spring的宏库使用。默认设置是“真实的”。目前需要为Spring的Velocity和FreeMarker默认宏。注意,对于使用HTML表单的模板,这不是必需的,除非您希望利用Spring helper宏。

@Override  protected final void renderMergedOutputModel(      Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {    if (this.exposeRequestAttributes) {      for (Enumeration<String> en = request.getAttributeNames(); en.hasMoreElements();) {        String attribute = en.nextElement();        if (model.containsKey(attribute) && !this.allowRequestOverride) {          throw new ServletException("Cannot expose request attribute '" + attribute +            "' because of an existing model object of the same name");        }        Object attributeValue = request.getAttribute(attribute);        if (logger.isDebugEnabled()) {          logger.debug("Exposing request attribute '" + attribute +              "' with value [" + attributeValue + "] to model");        }        model.put(attribute, attributeValue);      }    }    if (this.exposeSessionAttributes) {      HttpSession session = request.getSession(false);      if (session != null) {        for (Enumeration<String> en = session.getAttributeNames(); en.hasMoreElements();) {          String attribute = en.nextElement();          if (model.containsKey(attribute) && !this.allowSessionOverride) {            throw new ServletException("Cannot expose session attribute '" + attribute +              "' because of an existing model object of the same name");          }          Object attributeValue = session.getAttribute(attribute);          if (logger.isDebugEnabled()) {            logger.debug("Exposing session attribute '" + attribute +                "' with value [" + attributeValue + "] to model");          }          model.put(attribute, attributeValue);        }      }    }    if (this.exposeSpringMacroHelpers) {      if (model.containsKey(SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE)) {        throw new ServletException(            "Cannot expose bind macro helper '" + SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE +            "' because of an existing model object of the same name");      }      // Expose RequestContext instance for Spring macros.      model.put(SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE,          new RequestContext(request, response, getServletContext(), model));    }    applyContentType(response);//    模板方法    renderMergedTemplateModel(model, request, response);  }

渲染输出model,这里是模板方法实现,org.springframework.web.servlet.view.AbstractTemplateView#applyContentType 将“contentType”bean属性中指定的视图内容类型应用于给定的响应。只有在响应上没有设置内容类型的情况下,才应用视图的contentType。这允许处理程序预先覆盖默认的内容类型。

protected void applyContentType(HttpServletResponse response)  {    if (response.getContentType() == null) {      response.setContentType(getContentType());    }  }

org.springframework.web.servlet.view.AbstractTemplateView#renderMergedTemplateModel 子类必须实现这个方法来实际呈现视图。

protected abstract void renderMergedTemplateModel(      Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception;

org.springframework.web.servlet.view.freemarker.FreeMarkerView 使用FreeMarker模板引擎查看。

公开以下JavaBean属性:url:要包装的FreeMarker模板相对于FreeMarker模板上下文(目录)的位置。编码(可选,默认由FreeMarker配置决定):FreeMarker模板文件的编码,依赖于一个单独的FreeMarkerConfig对象,例如FreeMarkerConfigurer,可以在当前web应用程序上下文中使用任何bean名称进行访问。或者,您可以将FreeMarker配置对象设置为bean属性。注意:Spring对FreeMarker的支持要求FreeMarker 2.3或更高。

private String encoding;

encoding

@Override  protected void initServletContext(ServletContext servletContext) throws BeansException {    if (getConfiguration() != null) {      this.taglibFactory = new TaglibFactory(servletContext);    }    else {      FreeMarkerConfig config = autodetectConfiguration();      setConfiguration(config.getConfiguration());      this.taglibFactory = config.getTaglibFactory();    }    GenericServlet servlet = new GenericServletAdapter();    try {//      初始化servlet      servlet.init(new DelegatingServletConfig());    }    catch (ServletException ex) {      throw new BeanInitializationException("Initialization of GenericServlet adapter failed", ex);    }    this.servletContextHashModel = new ServletContextHashModel(servlet, getObjectWrapper());  }

在启动时调用。查找单个FreeMarkerConfig bean以查找此工厂的相关配置。检查是否可以找到默认语言环境的模板:如果没有找到特定于语言环境的模板,FreeMarker将检查非特定于语言环境的模板。

@Override  protected void renderMergedTemplateModel(      Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {    exposeHelpers(model, request);    doRender(model, request, response);  }

通过将模型映射与FreeMarker模板合并来处理它。输出被定向到servlet响应。如果需要自定义行为,可以重写此方法。

  @Override  protected void renderMergedTemplateModel(      Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {    exposeHelpers(model, request);//    渲染模型    doRender(model, request, response);  }

org.springframework.web.servlet.view.freemarker.FreeMarkerView#exposeHelpers 公开每个呈现操作唯一的助手。这是必要的,以便不同的呈现操作不会覆盖彼此的格式等。叫renderMergedTemplateModel。默认实现为空。可以重写此方法以向模型中添加自定义助手。

protected void exposeHelpers(Map<String, Object> model, HttpServletRequest request) throws Exception {  }

org.springframework.web.servlet.view.freemarker.FreeMarkerView#doRender 使用包含要使用的完整模板模型的给定模型映射,将FreeMarker视图呈现给给定的响应。默认实现呈现由“url”bean属性指定的模板,该属性通过getTemplate检索。它委托processTemplate方法将模板实例与给定的模板模型合并。将标准的Freemarker散列模型添加到模型中:请求参数、请求、会话和应用程序(ServletContext),以及JSP标记库散列模型。可以重写以自定义行为,例如将多个模板呈现到单个视图中。

protected void doRender(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {    // Expose model to JSP tags (as request attributes). 解析请求参数    exposeModelAsRequestAttributes(model, request);    // Expose all standard FreeMarker hash models. 构建模板模型    SimpleHash fmModel = buildTemplateModel(model, request, response);    if (logger.isDebugEnabled()) {      logger.debug("Rendering FreeMarker template [" + getUrl() + "] in FreeMarkerView '" + getBeanName() + "'");    }    // Grab the locale-specific version of the template.    Locale locale = RequestContextUtils.getLocale(request);//    处理模板    processTemplate(getTemplate(locale), fmModel, response);  }

org.springframework.web.servlet.view.json.AbstractJackson2View 抽象基类,用于基于Jackson和内容类型独立的AbstractView实现。

private ObjectMapper objectMapper;

objectMapper

@Override  protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) {    setResponseContentType(request, response);    response.setCharacterEncoding(this.encoding.getJavaName());    if (this.disableCaching) {      response.addHeader("Cache-Control", "no-store");    }  }

设置响应contentType、缓存相关header

  @Override  protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,      HttpServletResponse response) throws Exception {    OutputStream stream = (this.updateContentLength ? createTemporaryOutputStream() : response.getOutputStream());    Object value = filterAndWrapModel(model, request);    writeContent(stream, value);    if (this.updateContentLength) {      writeToResponse(response, (ByteArrayOutputStream) stream);    }  }

渲染输出model

org.springframework.web.servlet.view.xml.MappingJackson2XmlView Spring MVC视图,通过使用Jackson 2的XmlMapper序列化当前请求的模型来呈现XML内容。要序列化的对象作为模型中的参数提供。使用第一个可序列化条目。用户可以通过sourceKey属性在模型中指定一个特定的条目。默认构造函数使用Jackson2ObjectMapperBuilder提供的默认配置。

public static final String DEFAULT_CONTENT_TYPE = "application/xml";

默认contentType

  @Override  protected Object filterModel(Map model) {    Object value = null;    if (this.modelKey != null) {      value = model.get(this.modelKey);      if (value == null) {        throw new IllegalStateException(            "Model contains no object with key [" + this.modelKey + "]");      }    }    else {      for (Map.Entry entry : model.entrySet()) {        if (!(entry.getValue() instanceof BindingResult) && !entry.getKey().equals(JsonView.class.getName())) {          if (value != null) {            throw new IllegalStateException("Model contains more than one object to render, only one is supported");          }          value = entry.getValue();        }      }    }    return value;  }

解析json model

org.springframework.web.servlet.view.json.MappingJackson2JsonView Spring MVC视图,通过使用Jackson 2的ObjectMapper序列化当前请求的模型来呈现JSON内容。默认情况下,模型映射的整个内容(框架特定类除外)将被编码为JSON。如果模型只包含一个键,您可以通过setExtractValueFromSingleKeyModel将其提取编码为JSON。默认构造函数使用Jackson2ObjectMapperBuilder提供的默认配置。

public static final String DEFAULT_CONTENT_TYPE = "application/json";

默认内容类型:“application/json”。通过setContentType重写的。

public void setExtractValueFromSingleKeyModel(boolean extractValueFromSingleKeyModel) {    this.extractValueFromSingleKeyModel = extractValueFromSingleKeyModel;  }

设置是将包含单个属性的模型序列化为映射,还是从模型中提取单个值并直接序列化它。设置此标志的效果类似于使用带有@ResponseBody请求处理方法的MappingJackson2HttpMessageConverter。默认的是假的

org.springframework.web.servlet.view.xml.MarshallingView 允许响应上下文作为编组器编组的结果呈现的Spring-MVC视图。将编组的对象作为模型中的参数提供,然后在响应呈现期间检测。用户可以通过sourceKey属性在模型中指定一个特定的条目,或者让Spring定位源对象。

public static final String DEFAULT_CONTENT_TYPE = "application/xml";

默认contentType

private Marshaller marshaller;

marshaller

@Override  protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,      HttpServletResponse response) throws Exception {    Object toBeMarshalled = locateToBeMarshalled(model);    if (toBeMarshalled == null) {      throw new IllegalStateException("Unable to locate object to be marshalled in model: " + model);    }    ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);    this.marshaller.marshal(toBeMarshalled, new StreamResult(baos));    setResponseContentType(request, response);    response.setContentLength(baos.size());    baos.writeTo(response.getOutputStream());  }

渲染输出model

org.springframework.web.servlet.view.document.AbstractXlsView 方便的超类,用于传统XLS格式的Excel文档视图。兼容Apache POI 3.5及更高版本。

  public AbstractXlsView() {    setContentType("application/vnd.ms-excel");  }

设置contentType=application/vnd.ms-excel

@Override  protected final void renderMergedOutputModel(      Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {    // Create a fresh workbook instance for this render step.    Workbook workbook = createWorkbook(model, request);    // Delegate to application-provided document code.模板方法    buildExcelDocument(model, workbook, request, response);    // Set the content type.    response.setContentType(getContentType());    // Flush byte array to servlet output stream.    renderWorkbook(workbook, response);  }

渲染视图model,这里是模板方法实现,org.springframework.web.servlet.view.document.AbstractXlsView#buildExcelDocument 给定模型,应用程序提供的子类必须实现此方法来填充Excel工作簿文档。

protected abstract void buildExcelDocument(      Map<String, Object> model, Workbook workbook, HttpServletRequest request, HttpServletResponse response)      throws Exception;

org.springframework.web.servlet.view.document.AbstractXlsxView Office 2007 XLSX格式(由POI-OOXML支持)中Excel文档视图的方便超类。兼容Apache POI 3.5及更高版本。

public AbstractXlsxView() {    setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");  }

设置contentType=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

org.springframework.web.servlet.view.document.AbstractXlsxStreamingView  Office 2007 XLSX格式的Excel文档视图,使用POI的流媒体变体,方便的超类。兼容Apache POI 3.9及更高版本。

org.springframework.web.servlet.view.document.AbstractPdfView PDF视图的抽象超类。特定于应用程序的视图类将扩展这个类。视图将保存在子类本身中,而不是在模板中。这个视图实现使用Bruno Lowagie的iText API。已知可以使用原始的iText 2.1.7及其分支OpenPDF。我们强烈推荐OpenPDF,因为它是积极维护的,并且修复了不可信PDF内容的一个重要漏洞。注:Internet Explorer需要一个"。扩展,因为它并不总是尊重声明的内容类型。

public AbstractPdfView() {    setContentType("application/pdf");  }

此构造函数设置适当的内容类型“application/pdf”。请注意,IE不会注意到这一点,但我们对此无能为力。生成的文档应该有一个“”。pdf”扩展。

@Override  protected final void renderMergedOutputModel(      Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {    // IE workaround: write into byte array first.IE工作区:写入字节数组第一。    ByteArrayOutputStream baos = createTemporaryOutputStream();    // Apply preferences and build metadata.    Document document = newDocument();    PdfWriter writer = newWriter(document, baos);    prepareWriter(model, writer, request);//    模板方法    buildPdfMetadata(model, document, request);    // Build PDF document.    document.open();//    模板方法    buildPdfDocument(model, document, writer, request, response);    document.close();    // Flush to HTTP response.    writeToResponse(response, baos);  }

渲染输出model,这里是模板方法实现。org.springframework.web.servlet.view.document.AbstractPdfView#buildPdfMetadata 填充iText文档的元字段(作者、标题等)。默认值是一个空实现。子类可以重写此方法来添加元字段,如标题、主题、作者、创建者、关键字等。此方法在将PdfWriter分配给文档后调用,并在调用Document .open()之前调用。

protected void buildPdfMetadata(Map<String, Object> model, Document document, HttpServletRequest request) {  }

org.springframework.web.servlet.view.document.AbstractPdfView#buildPdfDocument 子类必须实现此方法来构建给定模型的iText PDF文档。在Document.open()和Document.close()调用之间调用。请注意,传入的HTTP响应只用于设置cookie或其他HTTP报头。在此方法返回后,构建的PDF文档本身将自动写入响应。

protected abstract void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer,      HttpServletRequest request, HttpServletResponse response) throws Exception;

org.springframework.web.servlet.view.AbstractView#writeToResponse 将给定的临时输出流写入HTTP响应。

protected void writeToResponse(HttpServletResponse response, ByteArrayOutputStream baos) throws IOException {    // Write content type and also length (determined via byte array).    response.setContentType(getContentType());    response.setContentLength(baos.size());    // Flush byte array to servlet output stream.    ServletOutputStream out = response.getOutputStream();    baos.writeTo(out);    out.flush();  }

说在最后

本次解析仅代表个人观点,仅供参考。

77b9459f6b43a1edd0a365aeeb71b11e.gif

扫码进入技术微信群

a79ae0732a0754af2d6f33bffa87e834.png77292e3ae6739b2c9d24d09dd58c75b4.png3ad8811da6534091741bbb73087be141.png钉钉技术群

cbca633a8cbbbc6af1ac1f01a672b0ff.png

qq技术群

5f797df763037c3b8b04ad705c112c6a.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367346.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Xstream将XML转换为javabean的问题

1.问题&#xff1a;Xstream is not security 解决方法&#xff1a;加上 2.问题&#xff1a;如果没有第二行代码&#xff0c;会出现xstream forbiddenclassexception 解决方法&#xff1a;加上第二行&#xff0c;其中参数是要进行解析的对象&#xff01; 调用该方法&#xff1a;…

蚂蚁属性细微差别

每隔一段时间&#xff0c;我会想起Ant属性的一些细微差别 &#xff0c;一旦忘记它们&#xff0c;在与Ant交互时会引起混乱。 特别是&#xff0c; Ant属性 通常是不可变的 &#xff08;不包括Ant 1.8版本的 局部属性 &#xff09;&#xff0c;并且在其首次设置时“永久”设置&am…

《从零构建前后分离的web项目》准备 - 前端了解过关了吗?

前端基础架构和硬核介绍 技术栈的选择 首先我们构建前端架构需要对前端生态圈有一切了解&#xff0c;并且最好带有一定的技术前瞻性&#xff0c;好的技术架构可能日后会方便的扩展&#xff0c;减少重构的次数&#xff0c;即使重构也不需要大动干戈&#xff0c;我通常选型技术栈…

联想w540笔记本参数_2020年12月笔记本电脑推荐!联想、惠普、华为笔记本电脑推荐!18款高性价比笔记本电脑推荐!!!...

前言&#xff1a;笔记本电脑&#xff0c;主要分为三种&#xff1a;轻薄本<全能本<游戏本。轻薄本&#xff0c;又称办公笔记本电脑&#xff0c;因为轻薄方便携带&#xff0c;通常用于移动办公使用。全能本&#xff0c;就是把轻薄本的集显变成了小独显&#xff0c;增加了独…

【BZOJ 1098】办公楼(补图连通块个数,Bfs)

补图连通块个数这大概是一个套路吧&#xff0c;我之前没有见到过&#xff0c;想了好久都没有想出来QaQ 事实上这个做法本身就是一个朴素算法&#xff0c;但进行巧妙的实现&#xff0c;就可以分析出它的上界不会超过 $O(n m)$。 接下来介绍一下这个技巧&#xff1a; 很显然一个…

Spring MVC:资源

我从博客读者那里收到的最常见的问题之一是如何在Spring MVC的应用程序中使用CSS和javascript文件。 因此&#xff0c;这是撰写有关Spring MVC中资源使用情况的文章的好机会。 通常&#xff0c;我将使用基于Java的配置方法。 如今&#xff0c;很难想象没有CSS和JavaScript文件…

c语言读文件空格间隔,c语言文件流实现按单个词读取(以空格、分号等作间隔)...

c语言文件流实现按词读取(以空格、分号等作间隔)1.基本描述在之前的作业中&#xff0c;认真编写代码&#xff0c;从中发现不少知识积累上的欠缺。编程中使用到的c语言文件读取&#xff0c;要求是按照获取到一个完整的词&#xff0c;并对其进行处理。写有java或c语言源程序的.tx…

山东专升本access知识点_全国各省份每年的专升本考试大纲啥时候公布?考纲公布之前你该做什么?...

?星标/置顶专升本招考下一个上岸的就是你最近小编在专升本招考后台收到很多同学的留言&#xff0c;大多同学都是看到好多省都公布了专升本考试政策和大纲&#xff0c;却迟迟不见自己所在的省份出&#xff0c;于是火急火燎地找到小编来问&#xff1a;XX省的考试大纲到底啥时候出…

观点|蚂蚁金服玉伯:我们是如何从前端技术进化到体验科技的?

小蚂蚁说&#xff1a;王保平&#xff0c;花名玉伯。熟悉前端和SeaJS的人一定对这个名字不陌生。作为前端领域的一枚大大大牛&#xff0c;他现在担任蚂蚁金服体验技术部负责人。本文&#xff0c;他分享了他从前端一路进阶升级到体验科技的个人思考&#xff0c;并详细介绍了体验科…

excel 电阻并联计算_电路分析基础(5)-关于电阻,有些话我还是要说一说

电阻定义&#xff1a;导体对电流的阻碍作用就叫该导体的电阻。不同的导体&#xff0c;电阻一般不同&#xff0c;电阻是导体本身的一种性质。定义式如下&#xff1a;因此&#xff0c;我们应该清楚了欧姆定律的本质到底是什么&#xff0c;为啥电阻跟电压和电流没有关系&#xff0…

针对新手的Java EE7和Maven项目–第2部分–为我们的应用程序定义一场简单的战争...

从第一部分恢复 第1部分 我们刚刚定义了父 pom。 一种特殊的pom类型&#xff0c;它最终定义了我们的应用程序将要使用的库。 它还配置了所有用于打包我们应用程序每个模块的Maven工具。 您可以在此处 签出 -1部分示例代码。 因此&#xff0c;到目前为止&#xff0c;在将要开发…

postman实现从response headers中获取cookie,并将其设置为环境变量

1.最近在学习postman的使用方法,为了保证后续模块操作&#xff0c;必须在登录时获取的session值&#xff0c;并将其设置为环境变量&#xff0c;session的位置处于response headers里面返回的set-cookie参数&#xff0c;并且将set-cookie中的session通过split方法截取出来. 写法…

010 pandas的DataFrame

一&#xff1a;创建 1.通过二维数组进行创建 2.取值 取列,取位置的值 3.切片取值 这个和上面的有些不同&#xff0c;这里先取行&#xff0c;再取列 4.设定列索引 这里使用的行索引与上面不同。 5.通过字典的方式创建 6.索引 包含行索引&#xff0c;与列索引 7.修改列索引 转载于…

unity烘培单个物体_Unity可编程渲染管线(SRP)教程:二、自定义着色器

本文翻译自Catlike Coding&#xff0c;原作者&#xff1a;Jasper Flick。本文经原作者授权&#xff0c;转载请说明出处。原文链接在下&#xff1a;https://catlikecoding.com/unity/tutorials/scriptable-render-pipeline/custom-shaders/​catlikecoding.com本章内容如下&…

一套比较完整的前端技术选型,需要规整哪些东西,你知道不?

1. 背景及现状 随着前端开发复杂度的日益增加&#xff0c;各种优秀的组件框架也遍地开花。同时&#xff0c;我们面临业务规模的快速发展和工程师团队的不断扩张&#xff0c;如何解决资源整合、模块开发、项目部署、性能优化等问题势在必行。 2. 目标 根据背景和现状的分析&a…

asp.net core2.0里的Nlog

Microsoft.Extensions.Logging&#xff0c;到了Version2.0.0.0&#xff0c;没了AddNlog() ? ——我找不到输出的日志&#xff01; 。。。。。经过一番百度 step1:添加个Provider 这样&#xff0c;在Startup里Configure实现一个ILoger 如果在controller里使用&#xff1f;——…

golang jwt设置过期_听说你的JWT库用起来特别扭,推荐这款贼好用的!

以前一直使用的是jjwt这个JWT库&#xff0c;虽然小巧够用, 但对JWT的一些细节封装的不是很好。最近发现了一个更好用的JWT库nimbus-jose-jwt&#xff0c;简单易用&#xff0c;API非常易于理解&#xff0c;对称加密和非对称加密算法都支持&#xff0c;推荐给大家&#xff01;简介…

随机验证码 pillow

安装 pip3 install pillow 基本使用 import PILfrom PIL import Imagefrom PIL import ImageDraw, ImageFontimport random 1.创建图片 from PIL import Image img Img.new(mode"RGB",size(120.30),color(255,255,255))# 在图片查看器中打开 # img.show()# 保存在本地…

微信小程序裁剪图片成圆形

前言 最近在开发小程序&#xff0c;产品经理提了一个需求&#xff0c;要求微信小程序换头像&#xff0c;用户剪裁图片必须是圆形&#xff0c;也在github上看了一些例子&#xff0c;一般剪裁图片用的都是方形&#xff0c;所以自己打算写一个小组件&#xff0c;可以把图片剪裁成圆…

MFC控件编程之组合框跟列表框

MFC控件编程之组合框跟列表框 一丶简介 如果要使用组合框跟列表框.那么就要知道.组合框列表框是最核心的东西就是索引. 索引是从0开始的. 二丶组合框列表框常用的方法 AddString(字符串) 添加一个字符串.放到最后面. DeleteString(索引); 删除指定索引的字符串. int GetCurSe…