SpringMVC请求处理流程:DispatcherServlet工作原理

news2025/3/6 19:43:58

在这里插入图片描述

文章目录

    • 引言
    • 一、DispatcherServlet概述
    • 二、DispatcherServlet初始化过程
    • 三、请求接收与处理器匹配
    • 四、请求参数绑定与处理器执行
    • 五、视图解析与渲染
    • 六、异常处理机制
    • 总结

引言

SpringMVC框架是Java Web开发中最流行的MVC框架之一,其核心组件DispatcherServlet作为前端控制器,负责协调整个请求处理流程。理解DispatcherServlet的工作原理对于掌握SpringMVC框架至关重要,不仅有助于开发高质量的Web应用,还能在遇到问题时快速定位和解决。本文将深入剖析SpringMVC的请求处理流程,揭示DispatcherServlet的内部运作机制,通过代码示例展示各个环节的实现细节,帮助开发者全面把握SpringMVC的核心工作流程,从而更加高效地进行Web应用开发。

一、DispatcherServlet概述

DispatcherServlet是SpringMVC框架的核心,它扮演着前端控制器(Front Controller)的角色,是整个请求处理流程的调度中心。作为一个标准的Servlet,DispatcherServlet继承自HttpServlet,遵循Servlet生命周期,在Web容器启动时初始化并加载SpringMVC相关配置。它的主要职责是接收HTTP请求,并根据请求信息将其分发给相应的处理器(Handler),随后协调视图解析器(ViewResolver)渲染结果,最终返回响应给客户端。这种集中式的请求处理机制极大地简化了Web开发的复杂性,实现了松耦合的MVC架构模式。

import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

/**
 * 通过编程方式注册DispatcherServlet
 * 这通常在Servlet 3.0+环境的WebApplicationInitializer实现类中完成
 */
public class MyWebAppInitializer implements org.springframework.web.WebApplicationInitializer {
    
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // 创建Spring Web应用上下文
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        // 注册配置类
        context.register(WebConfig.class);
        
        // 创建并注册DispatcherServlet
        DispatcherServlet dispatcherServlet = new DispatcherServlet(context);
        ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcher", dispatcherServlet);
        
        // 配置DispatcherServlet
        registration.setLoadOnStartup(1); // 设置启动优先级
        registration.addMapping("/"); // 设置URL映射模式
        registration.setAsyncSupported(true); // 启用异步支持
        
        // 可以添加初始化参数
        registration.setInitParameter("throwExceptionIfNoHandlerFound", "true");
    }
}

二、DispatcherServlet初始化过程

DispatcherServlet的初始化是整个SpringMVC框架启动的关键环节。当Web容器启动时,DispatcherServlet会执行初始化流程,创建Spring应用上下文(WebApplicationContext),并加载各种处理请求所需的组件。初始化过程主要分为两个阶段:Servlet标准初始化和SpringMVC特定初始化。在标准初始化阶段,容器调用DispatcherServlet的init()方法;在SpringMVC特定初始化阶段,它会初始化九大组件,包括HandlerMapping、HandlerAdapter、ViewResolver等。这些组件共同构成了SpringMVC的核心处理能力,为后续的请求处理提供必要支持。

import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

/**
 * SpringMVC配置类,配置DispatcherServlet所需的核心组件
 */
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    
    /**
     * 配置HandlerMapping,负责请求与处理器的映射
     */
    @Bean
    public HandlerMapping handlerMapping() {
        RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping();
        // 可以设置相关属性
        mapping.setOrder(0); // 设置优先级
        mapping.setUseSuffixPatternMatch(false); // 禁用后缀模式匹配
        return mapping;
    }
    
    /**
     * 配置HandlerAdapter,负责执行处理器
     */
    @Bean
    public HandlerAdapter handlerAdapter() {
        return new RequestMappingHandlerAdapter();
    }
    
    /**
     * 配置ViewResolver,负责解析视图
     */
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
    
    // 可以配置其他组件,如LocaleResolver、ThemeResolver等
}

三、请求接收与处理器匹配

当客户端发送HTTP请求到达Web服务器后,DispatcherServlet首先接收请求并开始处理流程。DispatcherServlet通过调用doService()方法,将请求委托给doDispatch()方法进行具体处理。在这个阶段,DispatcherServlet会遍历所有注册的HandlerMapping实现,查找与当前请求匹配的Handler(处理器)。常用的HandlerMapping包括RequestMappingHandlerMapping(基于注解)和SimpleUrlHandlerMapping(基于URL配置)。一旦找到匹配的Handler,DispatcherServlet还会获取相关的拦截器(Interceptor),组合形成HandlerExecutionChain(处理器执行链),为后续的请求处理做准备。

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 控制器示例,演示请求映射
 */
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @GetMapping
    public String listUsers(@RequestParam(required = false) String filter) {
        // 处理获取用户列表请求
        return "User list filtered by: " + (filter != null ? filter : "none");
    }
    
    @GetMapping("/{id}")
    public String getUserById(@PathVariable Long id) {
        // 处理获取特定用户请求
        return "User details for ID: " + id;
    }
}

/**
 * 自定义拦截器,将被添加到HandlerExecutionChain中
 */
@Component
public class LoggingInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("LoggingInterceptor.preHandle: " + request.getRequestURI());
        // 返回true继续处理,返回false中断处理
        return true;
    }
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        System.out.println("LoggingInterceptor.postHandle: " + request.getRequestURI());
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("LoggingInterceptor.afterCompletion: " + request.getRequestURI());
        if (ex != null) {
            System.out.println("Exception occurred: " + ex.getMessage());
        }
    }
}

/**
 * 配置拦截器,将其注册到SpringMVC框架
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoggingInterceptor())
                .addPathPatterns("/api/**") // 指定拦截路径
                .excludePathPatterns("/api/public/**"); // 指定排除路径
    }
}

四、请求参数绑定与处理器执行

找到匹配的Handler后,DispatcherServlet需要调用合适的HandlerAdapter来执行处理器。在SpringMVC中,最常用的是RequestMappingHandlerAdapter,它负责执行基于@RequestMapping注解的控制器方法。在执行前,HandlerAdapter会进行请求参数的解析与绑定,将HTTP请求中的参数转换为控制器方法所需的参数。这个过程涉及多种类型转换器和参数解析器,如RequestParamMethodArgumentResolver、PathVariableMethodArgumentResolver等。参数绑定完成后,HandlerAdapter调用控制器方法,执行业务逻辑,并获取处理结果(ModelAndView或返回值)。这一阶段是整个请求处理的核心环节。

import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.beans.propertyeditors.CustomDateEditor;

import javax.validation.Valid;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 演示参数绑定的控制器
 */
@Controller
@RequestMapping("/products")
public class ProductController {
    
    /**
     * 初始化WebDataBinder,用于自定义参数绑定规则
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        // 注册自定义日期编辑器
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
    }
    
    /**
     * 展示创建产品表单
     */
    @GetMapping("/new")
    public String showCreateForm(Model model) {
        model.addAttribute("product", new Product());
        return "product/create";
    }
    
    /**
     * 处理产品创建请求
     * 演示多种参数绑定方式
     */
    @PostMapping
    public String createProduct(
            @Valid @ModelAttribute("product") Product product, // 表单对象绑定和验证
            BindingResult bindingResult, // 验证结果
            @RequestParam(required = false) String category, // 请求参数
            @CookieValue(value = "sessionId", required = false) String sessionId, // Cookie值
            @RequestHeader("User-Agent") String userAgent, // 请求头
            Model model // 模型
    ) {
        // 检查验证结果
        if (bindingResult.hasErrors()) {
            return "product/create";
        }
        
        // 执行业务逻辑
        System.out.println("Creating product: " + product.getName());
        System.out.println("Category: " + category);
        System.out.println("Session ID: " + sessionId);
        System.out.println("User Agent: " + userAgent);
        
        // 添加成功消息到模型
        model.addAttribute("message", "Product created successfully!");
        return "redirect:/products";
    }
}

/**
 * 产品实体类
 */
public class Product {
    private Long id;
    private String name;
    private Double price;
    private Date releaseDate;
    
    // Getters and Setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    public Double getPrice() { return price; }
    public void setPrice(Double price) { this.price = price; }
    
    public Date getReleaseDate() { return releaseDate; }
    public void setReleaseDate(Date releaseDate) { this.releaseDate = releaseDate; }
}

五、视图解析与渲染

当控制器方法执行完毕后,它通常会返回一个逻辑视图名或直接返回数据。对于返回逻辑视图名的情况,DispatcherServlet需要将其解析为具体的视图对象。视图解析过程由ViewResolver接口的实现类负责,如InternalResourceViewResolver(用于JSP)、ThymeleafViewResolver(用于Thymeleaf模板)等。DispatcherServlet会遍历已注册的ViewResolver,查找能够解析当前逻辑视图名的解析器。一旦找到合适的视图对象,就会调用其render()方法,将模型数据(Model)渲染到视图中,生成响应内容。对于REST风格的接口,返回值可能被直接转换为JSON/XML,这种情况下不需要视图解析步骤。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 视图解析器配置类
 */
@Configuration
@EnableWebMvc
public class ViewResolverConfig implements WebMvcConfigurer {
    
    /**
     * 配置JSP视图解析器
     */
    @Bean
    public ViewResolver jspViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
        resolver.setOrder(2); // 设置优先级
        return resolver;
    }
    
    /**
     * 配置FreeMarker视图解析器
     */
    @Bean
    public ViewResolver freeMarkerViewResolver() {
        FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
        resolver.setCache(true);
        resolver.setPrefix("");
        resolver.setSuffix(".ftl");
        resolver.setContentType("text/html; charset=UTF-8");
        resolver.setOrder(1); // 优先级高于JSP解析器
        return resolver;
    }
    
    /**
     * 配置FreeMarker引擎
     */
    @Bean
    public FreeMarkerConfigurer freeMarkerConfigurer() {
        FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
        configurer.setTemplateLoaderPath("/WEB-INF/templates/");
        configurer.setDefaultEncoding("UTF-8");
        return configurer;
    }
    
    /**
     * 内容协商视图解析器配置
     */
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.enableContentNegotiation(new MappingJackson2JsonView());
    }
}

/**
 * 演示不同视图解析方式的控制器
 */
@Controller
public class ViewController {
    
    /**
     * 返回JSP视图
     */
    @GetMapping("/page/jsp")
    public String jspView(Model model) {
        model.addAttribute("message", "Hello from JSP!");
        return "hello"; // 解析为/WEB-INF/views/hello.jsp
    }
    
    /**
     * 返回FreeMarker视图
     */
    @GetMapping("/page/freemarker")
    public String freemarkerView(Model model) {
        model.addAttribute("message", "Hello from FreeMarker!");
        return "hello"; // 解析为/WEB-INF/templates/hello.ftl
    }
    
    /**
     * 直接返回ModelAndView
     */
    @GetMapping("/page/manual")
    public ModelAndView manualView() {
        ModelAndView mav = new ModelAndView("custom");
        mav.addObject("message", "Hello from custom view!");
        return mav;
    }
    
    /**
     * 返回JSON数据(不使用视图解析)
     */
    @GetMapping("/api/data/{id}")
    @ResponseBody
    public Product jsonData(@PathVariable Long id) {
        Product product = new Product();
        product.setId(id);
        product.setName("Sample Product");
        product.setPrice(99.99);
        return product; // 直接转换为JSON返回
    }
}

六、异常处理机制

在请求处理过程中,可能会发生各种异常,如业务逻辑异常、参数验证异常等。SpringMVC提供了完善的异常处理机制,由DispatcherServlet协调,确保异常被正确处理并返回适当的响应。核心组件是HandlerExceptionResolver接口的实现类,包括DefaultHandlerExceptionResolver(处理标准Spring异常)、ExceptionHandlerExceptionResolver(处理@ExceptionHandler注解)等。当异常发生时,DispatcherServlet会遍历已注册的异常解析器,查找能够处理当前异常的解析器。异常处理可以通过@ExceptionHandler注解、@ControllerAdvice全局异常处理类或实现HandlerExceptionResolver接口来自定义。良好的异常处理设计能够提高系统的健壮性和用户体验。

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.validation.BindException;

import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.Date;

/**
 * 全局异常处理器
 */
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    
    /**
     * 处理业务逻辑异常
     */
    @ExceptionHandler(BusinessException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public ErrorResponse handleBusinessException(BusinessException ex) {
        return new ErrorResponse(
                HttpStatus.INTERNAL_SERVER_ERROR.value(),
                ex.getMessage(),
                new Date()
        );
    }
    
    /**
     * 处理资源未找到异常
     */
    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ResponseBody
    public ErrorResponse handleResourceNotFoundException(ResourceNotFoundException ex) {
        return new ErrorResponse(
                HttpStatus.NOT_FOUND.value(),
                ex.getMessage(),
                new Date()
        );
    }
    
    /**
     * 处理参数验证异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public Map<String, Object> handleValidationExceptions(ConstraintViolationException ex) {
        Map<String, Object> errors = new HashMap<>();
        ex.getConstraintViolations().forEach(violation -> {
            String fieldName = violation.getPropertyPath().toString();
            String errorMessage = violation.getMessage();
            errors.put(fieldName, errorMessage);
        });
        return errors;
    }
    
    /**
     * 处理404错误(需配置throwExceptionIfNoHandlerFound=true)
     */
    @Override
    protected ResponseEntity<Object> handleNoHandlerFoundException(
            NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        
        ErrorResponse error = new ErrorResponse(
                HttpStatus.NOT_FOUND.value(),
                "Resource not found: " + ex.getRequestURL(),
                new Date()
        );
        
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }
    
    /**
     * 处理表单绑定异常
     */
    @Override
    protected ResponseEntity<Object> handleBindException(
            BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error -> 
            errors.put(error.getField(), error.getDefaultMessage())
        );
        
        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }
    
    /**
     * 处理所有其他未捕获的异常
     */
    @ExceptionHandler(Exception.class)
    public ModelAndView handleGenericException(Exception ex) {
        ModelAndView modelAndView = new ModelAndView("error/generic");
        modelAndView.addObject("errorMessage", ex.getMessage());
        modelAndView.addObject("timestamp", new Date());
        return modelAndView;
    }
}

/**
 * 自定义业务异常
 */
public class BusinessException extends RuntimeException {
    public BusinessException(String message) {
        super(message);
    }
}

/**
 * 自定义资源未找到异常
 */
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

/**
 * 错误响应DTO
 */
public class ErrorResponse {
    private int status;
    private String message;
    private Date timestamp;
    
    public ErrorResponse(int status, String message, Date timestamp) {
        this.status = status;
        this.message = message;
        this.timestamp = timestamp;
    }
    
    // Getters and Setters
    public int getStatus() { return status; }
    public void setStatus(int status) { this.status = status; }
    
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }
    
    public Date getTimestamp() { return timestamp; }
    public void setTimestamp(Date timestamp) { this.timestamp = timestamp; }
}

总结

SpringMVC的请求处理流程是一个精心设计的管道,由DispatcherServlet作为中央调度器协调各个组件的工作。这一流程始于DispatcherServlet接收HTTP请求,随后通过HandlerMapping查找匹配的Handler,利用HandlerAdapter执行处理器逻辑,最后通过ViewResolver解析视图并渲染响应结果。整个过程高度模块化,各组件职责明确,通过策略模式和组合模式实现了高度的可扩展性和灵活性。了解这一流程不仅有助于开发者编写高质量的代码,还能在遇到问题时快速定位根源。在实际应用中,可以通过自定义HandlerMapping、HandlerAdapter、ViewResolver等组件来扩展框架能力,满足特定业务需求。此外,合理配置拦截器和异常处理器,能够提升应用的安全性和用户体验。掌握SpringMVC的请求处理流程对于Java Web开发者而言是至关重要的基础知识,是构建高性能、可维护Web应用的关键。

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

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

相关文章

解锁数据潜能,永洪科技以数据之力简化中粮可口可乐决策之路

企业数字化转型是指企业利用数字技术和信息通信技术来改变自身的商业模式、流程和增值服务&#xff0c;以提高企业的竞争力和创新能力。数字化转型已经成为企业发展的重要战略&#xff0c;尤其在当前信息技术高速发展的时代。数字化转型还涉及到企业与消费者之间的互动和沟通。…

双链路提升网络传输的可靠性扩展可用带宽

为了提升网络传输的可靠性或增加网络可用带宽&#xff0c; 通常使用双链路冗余备份或者双链路聚合的方式。 本文介绍几种双链路网络通信的案例。 5GWiFi冗余传输 双Socket绑定不同网络接口&#xff1a;通过Android的ConnectivityManager绑定5G蜂窝网络和WiFi的Socket连接&…

前端性能优化之同时插入100000个元素页面不卡顿

面试官&#xff1a;同时插入100000个元素怎么让页面不卡顿 优化前写法 首先我们来看下面的一段&#xff0c;点击按钮后&#xff0c;循环100000次&#xff0c;每次都插入一个元素&#xff0c;并且插入区域上方还有一个小球在滚动&#xff0c;在插入的过程中我们可以观察小球的…

Exoplayer2源码编译FFmpeg拓展模块实现音频软解码

在前面文章最新版本Exoplayer扩展FFmpeg音频软解码保姆级教程中介绍了最新版本的Exoplayer(androidx.Media3)编译FFmpeg模块的流程&#xff0c;有就是media3版本的explayer最低支持的sdk版本是21也就是Android5.x,但是市面上还是有很多IOT设备是很老的android4.4(sdk19)的&…

Docker安装嵌入框架Text Embeddings Inference (TEI)

Docker安装Text Embeddings Inference (TEI) 1 简单介绍 文本嵌入推理&#xff08;TEI&#xff0c;Text Embeddings Inference &#xff09;是HuggingFace研发的一个用于部署和服务开源文本嵌入和序列分类模型的工具包。TEI兼容OpenAI的嵌入模型的规范。 # 官网地址 https:/…

MAUI(C#)安卓开发起步

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

PPT小黑第26套

对应大猫28 层次级别是错的&#xff0c;看着是十页&#xff0c;导入ppt之后四十多页 选中所有 红色蓝色黑色 文本选择标题&#xff1a;选择 -格式相似文本&#xff08;检查有没有漏选 漏选的话 按住ctrl 点下一个&#xff09; 要求新建幻灯片中不包含原素材中的任何格式&…

【Linux-网络】HTTP的清风与HTTPS的密语

&#x1f3ac; 个人主页&#xff1a;谁在夜里看海. &#x1f4d6; 个人专栏&#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长&#xff0c;行则将至 目录 &#x1f4da; 引言 &#x1f4da; 一、HTTP &#x1f4d6; 1.概述 &#x1f4d6; 2.URL &#x1f5…

解决docker认证问题 failed to authorize: failed to fetch oauth token

报错信息[bash1]解决方案 全局代理打开“buildkit”: false &#xff0c;见[图1] [bash1] >docker build -t ffpg . [] Building 71.8s (3/3) FINISHED docker:desktop-linux> [internal] load bui…

无人机应用探索:玻纤增强复合材料的疲劳性能研究

随着无人机技术的快速发展&#xff0c;轻量化已成为其结构设计的核心需求。玻纤增强复合材料凭借高强度、低密度和优异的耐环境性能&#xff0c;成为无人机机身、旋翼支架等关键部件的理想选择。然而&#xff0c;无人机在服役过程中需应对复杂多变的环境&#xff1a;高空飞行时…

Visual Studio工具

高亮显示匹配的标签&#xff08;小括号&#xff0c;中括号&#xff0c;大括号&#xff09;

STM32Cubemx配置E22-xxxT22D lora模块实现定点传输

文章目录 一、STM32Cubemx配置二、定点传输**什么是定点传输&#xff1f;****定点传输的特点****定点传输的工作方式****E22 模块定点传输配置****如何启用定点传输&#xff1f;****示例** **应用场景****总结** **配置 1&#xff1a;C0 00 07 00 02 04 62 00 17 40****解析** …

WPF+WebView 基础

1、基于.NET8&#xff0c;通过NuGet添加Microsoft.Web.WebView2。 2、MainWindow.xaml代码如下。 <Window x:Class"Demo.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/win…

蓝桥杯算法——铠甲合体

问题描述 暗影大帝又开始搞事情了&#xff01;这次他派出了 MM 个战斗力爆表的暗影护法&#xff0c;准备一举摧毁 ERP 研究院&#xff01;MM 个暗影护法的战斗力可分别用 B1,⋯,BMB1​,⋯,BM​ 表示。 ERP 研究院紧急召唤了 NN 位铠甲勇士前来迎战&#xff01;每位铠甲勇士都…

docker:Dockerfile案例之自定义centos7镜像

1 案例需求 自定义centos7镜像。要求&#xff1a; 默认登录路径为 /usr可以使用vim 2 实施步骤 编写dockerfile脚本 vim centos_dockerfile 内容如下&#xff1a; #定义父镜像 FROM centos:7#定义作者信息 MAINTAINER handsome <handsomehandsome.com># 设置阿里云…

学习笔记:IC存储总结(ROM,RAM, EEPROM, Flash, SRAM, DRAM, DDL)

一&#xff0c;概述 半导体存储器是一种可以存储大量二值信息的半导体器件。在电子计算机及一些其他的数字系统的工作过程中&#xff0c;需要对大量的数据进行储存。由于数据处理的数据量和运算速度的要求&#xff0c;因此把存储量和存取速度作为衡量存储器的重要指标。 在电子…

Scala:统计每个单词出现的个数并打印

目录 问题拆解&#xff1a; 解题步骤&#xff1a; 1. 拆分所有字符串为单词 2. 遍历所有单词并统计 3. 打印结果 基础版代码实现&#xff1a; 代码解释&#xff1a; 输出结果&#xff1a; 为什么这样设计&#xff1f; 继承的APP是个啥&#xff1f; 使用高阶函数式编…

C++前缀和

个人主页&#xff1a;[PingdiGuo_guo] 收录专栏&#xff1a;[C干货专栏] 大家好&#xff0c;今天我们来了解一下C的一个重要概念&#xff1a;前缀和 目录 1.什么是前缀和 2.前缀和的用法 1.前缀和的定义 2.预处理前缀和数组 3.查询区间和 4.数组中某个区间的和是否为特定…

图解MOE大模型的7个核心问题并探讨DeepSeekMoE的专家机制创新

原文地址:https://newsletter.maartengrootendorst.com/p/a-visual-guide-to-mixture-of-experts #mermaid-svg-FU7YUSIfuXO6EVHa {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-FU7YUSIfuXO6EVHa .error-icon{fill…

SpringBoot项目集成ElasticSearch

1. 项目背景 处于失业找工作的阶段&#xff0c;随便写写吧~ 没啥背景&#xff0c;没啥意义&#xff0c;Java后端越来越卷了。第一学历不是本科&#xff0c;感觉真的是没有一点路可走。 如果有路过的小伙伴&#xff0c;如果身边还有坑位&#xff0c;不限第一学历的话&#xff0…