手写SpringMVC开发框架

运行环境

JDK :17
IntelliJ IDEA : 2022.3
Tomcat:8.5.86

前期工作

  1. 先创建一个新的Maven项目,按照图示操作:
    在这里插入图片描述
  2. 在这里我们选择Maven Archetype选项,写好项目名称:Handwriting-SpringMVC,以及路径并选好Archetype为webapp。点击creat创建。
    在这里插入图片描述
  3. 编辑环境:按照图示选择对应的选项,最后点击OK即可!
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    注意:在开始本项目前你需要了解一些MVC常用注解及其流程。

项目结构

项目类继承关系
在这里插入图片描述

main结构

在这里插入图片描述
在这里插入图片描述
java
com.bruce.controller:用户自定义的SpringMVC控制层
com.bruce.pojo:用户自定义的对象(User)
com.bruce.service:用户自定义的接口和实现类(UserService、UserServiceImpl)

com.springmvc.annotation:SpringMVC的相关注解
com.springmvc.context:Spring容器
com.springmvc.exception:用户自定义异常
com.springmvc.handler:负责处理HTTP请求的组件
com.springmvc.servlet:SpringMVC的核心控制器
com.springmvc.xml:解析springmvc.xml文件

resources
目前只有一个springmvc.xml文件

webapp
WEB-INF:Java的Web应用的安全目录


test结构
在这里插入图片描述
java
com.bruce.test:测试XML解析工具

resources
NULL


两个重要的XML文件和一个JSP文件:

  • springmvc.xml:SpringMVC的配置文件
  • web.xml:web应用的配置文件。
  • user.jsp:后面用来跳转的JSP文件
  • index.jsp:自动生成的,可以不用管 (非必须)
    在这里插入图片描述

项目流程

请添加图片描述
请添加图片描述

  1. 在启动Tomcat后就会自动解析webapp中的WEB-INF中的web.xml,所以我们先配置web.xml
  2. 创建DispatcherServlet(前端控制器)和WebApplicationContext(spring容器)
  3. 接下来会执行DispatcherServlet中的init()方法,创建Spring容器,并从springmvc.xml文件中读取base-package中的包路径,并生成对象,存放在iocMap
  4. 当我们的对象生成完毕之后,就会执行initHandlerMappring()方法,遍历spring容器中的iocMap,遍历其中所有的Controller类型的对象的Class对象,然后判断每一个Class对象中的所有方法,将有@RequestMapping注解的方法封装成一个MyHandler对象,其中包含@RequestMapping注解的名字(url),Controller对象(controller),该方法(method)。然后将这个MyHandler对象放到handlerList集合中。
  5. 当有get请求的时候,就会执行DispatcherServlet中的doGet()方法。遍历handlerList,寻找浏览器url请求路径和我们MyHandler对象中储存的@RequestMapping中相等的对象,然后定义一个参数的Object数组,经过一系列的关于@RequestParam参数的判断,将浏览器请求路径中的参数放到对应位置的Object数组中,然后通过handler.getMethod().invoke()执行这个方法就可以调用控制中的方法并获得返回值,然后做一个返回值类型的判断:String还是Json。最后做跳转JSP或返回JSON数据的代码逻辑。
  6. 最后运行的结果如下,成功跳转到我们的user.jsp文件中:

在这里插入图片描述

注意:整体的流程最好自己debug一遍,印象会更深刻!


pom.xml文件:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>Handwriting-SpringMVC</artifactId><packaging>war</packaging><version>1.0-SNAPSHOT</version><name>Handwriting-SpringMVC Maven Webapp</name><url>http://maven.apache.org</url><dependencies><!--单元测试--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!--解析XML文件--><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.5</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.8</version><scope>provided</scope></dependency><!--JSON转换工具--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.16.1</version></dependency></dependencies><build><finalName>Handwriting-SpringMVC</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>17</source><target>17</target><!--JDK8新特性,能够获取到方法中的参数--><!--[request, response, name]--><compilerArgs><arg>-parameters</arg></compilerArgs><encoding>UTF-8</encoding></configuration></plugin></plugins></build>
</project>

main


com.bruce.controller包:

UserController类:

package com.bruce.controller;import com.bruce.pojo.User;
import com.bruce.service.UserService;
import com.springmvc.annotation.Autowired;
import com.springmvc.annotation.Controller;
import com.springmvc.annotation.RequestMapping;
import com.springmvc.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;/*** @Author: Juechen* @Date: 2024/4/24* @Description: 控制器* @Version: 1.0**/
@Controller
public class UserController {// 持有业务逻辑层的对象@AutowiredUserService userService;@RequestMapping("/user/query")public String findUsers(HttpServletRequest request, HttpServletResponse response, String name) {// 处理响应的中文乱码问题response.setContentType("text/html;charset=utf-8");String message = userService.getMessage(name);request.setAttribute("message",message);//转发到user.jspreturn "forward:/user.jsp";}@RequestMapping("/user/queryjson")@ResponseBodypublic List<User> queryUsers(HttpServletRequest request, HttpServletResponse response, String name){return userService.findUsers(name);}}

com.bruce.pojo包:

User类:

package com.bruce.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @Author: Juechen* @Date: 2024/4/24* @Description: TODO* @Version: 1.0**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private Integer id;private String name;private String pass;}

com.bruce.service包:

UserService接口:

package com.bruce.service;import com.bruce.pojo.User;import java.util.List;public interface UserService {List<User> findUsers(String name);String getMessage(String name);}

com.bruce.service.impl包:

UserServiceImpl类:

package com.bruce.service.impl;import com.bruce.pojo.User;
import com.bruce.service.UserService;
import com.springmvc.annotation.Service;import java.util.ArrayList;
import java.util.List;/*** @Author: Juechen* @Date: 2024/4/24* @Description: UserService的实现类* @Version: 1.0**/
@Service  // 默认就是类名首字母小写public class UserServiceImpl implements UserService {@Overridepublic List<User> findUsers(String name) {// 模拟数据List<User> users = new ArrayList<>();users.add(new User(1,"老王","admin"));users.add(new User(2,"小王","12345"));return users;}@Overridepublic String getMessage(String name) {return "我是getMessage方法," + name;}
}

com.springmvc.annotation包:

Autowired注解:

package com.springmvc.annotation;import java.lang.annotation.*;@Target(ElementType.FIELD) // 元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {String value() default "";
}

Controller注解:

package com.springmvc.annotation;import java.lang.annotation.*;@Target(ElementType.TYPE) // 元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Controller {String value() default "";
}

RequestMapping注解:

package com.springmvc.annotation;import java.lang.annotation.*;@Target(ElementType.METHOD) // 元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestMapping {String value() default "";
}

RequestParm注解:

package com.springmvc.annotation;import java.lang.annotation.*;@Target(ElementType.PARAMETER) // 元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParm {String value() default "";
}

ResponseBody注解:

package com.springmvc.annotation;import java.lang.annotation.*;@Target(ElementType.METHOD) // 元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {}

Service注解:

package com.springmvc.annotation;import java.lang.annotation.*;@Target(ElementType.TYPE) // 元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Service {String value() default "";
}

com.springmvc.context包:

WebApplicationContext类:Spring容器

package com.springmvc.context;import com.springmvc.annotation.Autowired;
import com.springmvc.annotation.Controller;
import com.springmvc.annotation.Service;
import com.springmvc.exception.ContextException;
import com.springmvc.xml.XmlParser;import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @Author: Juechen* @Date: 2024/4/24* @Description: Spring容器* @Version: 1.0**/
public class WebApplicationContext {// classpath:springmvc.xmlString contextConfigLocation;List<String> classNameList = new ArrayList<>();// Spring的Ioc容器public Map<String, Object> iocMap = new ConcurrentHashMap<>();public WebApplicationContext(String contextConfigLocation) {this.contextConfigLocation = contextConfigLocation;}/*** 初始化Spring容器*/public void refresh() {// 1.解析springmvc.xml文件// split方法用于将字符串根据指定的正则表达式进行拆分,这里得到的是springmvc.xmlString basePackage = XmlParser.getbasePackage(contextConfigLocation.split(":")[1]);// 这里通过逗号分隔成了两个字符串:com.bruce.service 和 com.bruce.controllerString[] basePackages = basePackage.split(",");if (basePackages.length > 0) {for (String pack : basePackages) {// com.bruce.service// com.bruce.controllerexcuteScanPackage(pack);}}System.out.println("扫描后的结果是:" + classNameList);// 2.实例化Spring容器中的beanexcuteInstance();// Ioc容器中的对象是:System.out.println("spring的Ioc容器对象是:" + iocMap);// 3.需要实现spring容器中对象的注入excuteAutowired();}/*** 扫描包*/public void excuteScanPackage(String pack) {//  /com/bruce/serviceURL url = this.getClass().getClassLoader().getResource("/" + pack.replaceAll("\\.", "/"));String path = url.getFile();File dir = new File(path);for (File f : dir.listFiles()) {if (f.isDirectory()) {// 当前是一个文件目录excuteScanPackage(pack + "." + f.getName());} else {// 文件目录下文件  获取全路径String className = pack + "." + f.getName().replaceAll(".class", "");classNameList.add(className);}}}/*** 实例化Spring容器中的bean对象*/public void excuteInstance() {if (classNameList.size() == 0) {// 没有扫描到需要实例化的类throw new ContextException("没有要实例化的class!");}try {for (String className : classNameList) {Class<?> clazz = Class.forName(className);if (clazz.isAnnotationPresent(Controller.class)) {// 控制层的类  com.bruce.controller// UserController -> userController 控制层对象的名字String beanName = clazz.getSimpleName().substring(0, 1).toLowerCase() + clazz.getSimpleName().substring(1);iocMap.put(beanName, clazz.newInstance());} else if (clazz.isAnnotationPresent(Service.class)) {// 业务逻辑层的类 com.bruce.service.implService serviceAnnotation = clazz.getAnnotation(Service.class);String beanName = serviceAnnotation.value();if ("".equals(beanName)) {Class<?>[] interfaces = clazz.getInterfaces();for (Class<?> c1 : interfaces) {String beanName1 = c1.getSimpleName().substring(0, 1).toLowerCase() + c1.getSimpleName().substring(1);// 接口名字作为beanNameiocMap.put(beanName1, clazz.newInstance());}} else {iocMap.put(beanName, clazz.newInstance());}}}} catch (Exception e) {throw new RuntimeException(e);}}/*** 实现spring容器中的对象的依赖注入*/private void excuteAutowired() {try {if (iocMap.isEmpty()) {throw new ContextException("没有找到初始化的bean对象");}// Map的一种迭代方法for (Map.Entry<String, Object> entry : iocMap.entrySet()) {// 获取到了一个一个对象名称String key = entry.getKey();// 获取到了一个一个对象实例Object bean = entry.getValue();Field[] declaredFields = bean.getClass().getDeclaredFields();for (Field declaredField : declaredFields) {if (declaredField.isAnnotationPresent(Autowired.class)) {Autowired autowiredAnnotation = declaredField.getAnnotation(Autowired.class);String beanName = autowiredAnnotation.value();// 进一步判断是否设置了 value 属性,如果未设置,则根据字段的类型推断 bean 的名称。if (beanName.equals("")) {// 这个拿到的其实是属性类的全名称Class<?> type = declaredField.getType();// 做剪枝操作beanName = type.getSimpleName().substring(0, 1).toLowerCase() + type.getSimpleName().substring(1);}// 暴力反射,因为Controller层的属性类有可能是私有的declaredField.setAccessible(true);// 属性注入  调用反射给属性赋值declaredField.set(bean, iocMap.get(beanName));}}}} catch (IllegalAccessException e) {e.printStackTrace();}}
}

com.springmvc.exception包:

ContextException类:自定义异常

package com.springmvc.exception;/*** @Author: Juechen* @Date: 2024/4/24* @Description: 自定义异常* @Version: 1.0**/
public class ContextException extends RuntimeException {public ContextException(String message) {super(message);}public ContextException(Throwable cause) {super(cause);}@Overridepublic String getMessage() {return super.getMessage();}
}

com.springmvc.handler包:

MyHandler类:自定义的处理器对象

package com.springmvc.handler;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.lang.reflect.Method;/*** @Author: Juechen* @Date: 2024/4/25* @Description: 自定义的处理器对象* @Version: 1.0**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyHandler {private String url;private Object controller;private Method method;}

com.springmvc.servlet包:

DispatcherServlet类:SpringMVC的核心控制器

package com.springmvc.servlet;import com.fasterxml.jackson.databind.ObjectMapper;
import com.springmvc.annotation.Controller;
import com.springmvc.annotation.RequestMapping;
import com.springmvc.annotation.RequestParm;
import com.springmvc.annotation.ResponseBody;
import com.springmvc.context.WebApplicationContext;
import com.springmvc.exception.ContextException;
import com.springmvc.handler.MyHandler;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;/*** @Author: Juechen* @Date: 2024/4/24* @Description: SpringMVC的核心控制器* @Version: 1.0**/
public class DispatcherServlet extends HttpServlet {private WebApplicationContext webApplicationContext;// 存储url和对象方法的映射List<MyHandler> handlerList = new ArrayList<>();@Overridepublic void init() throws ServletException {// 1.Servlet初始化的时候,读取初始化的参数 classpath:springmvc.xmlString contextConfigLocation = this.getServletConfig().getInitParameter("contextConfigLocation");// 2.创建Spring容器webApplicationContext = new WebApplicationContext(contextConfigLocation);// 3.初始化Spring容器webApplicationContext.refresh();// 4.初始化请求映射  /user/query ----> Controller ----> method ----->parameterinitHandlerMappring();System.out.println(handlerList);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 进行请求分发处理excuteDispatch(req, resp);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}/*** 初始化请求映射*/private void initHandlerMappring() {//判断Iocmap中是否有bean对象if (webApplicationContext.iocMap.isEmpty()) {throw new ContextException("Spring容器为空");}for (Map.Entry<String, Object> entry : webApplicationContext.iocMap.entrySet()) {Class<?> clazz = entry.getValue().getClass();if (clazz.isAnnotationPresent(Controller.class)) {Method[] declaredMethods = clazz.getMethods();for (Method declaredMethod : declaredMethods) {if (declaredMethod.isAnnotationPresent(RequestMapping.class)) {RequestMapping requestMappingAnnotation = declaredMethod.getAnnotation(RequestMapping.class);//  ("/user/query")String url = requestMappingAnnotation.value();// 构造一个自定义的处理器对象MyHandler handler = new MyHandler(url, entry.getValue(), declaredMethod);handlerList.add(handler);}}}}}/*** 请求的分发处理*/public void excuteDispatch(HttpServletRequest req, HttpServletResponse resp) {MyHandler handler = getHandler(req);try {if (handler == null) {resp.getWriter().print("<h1>404 NOT FOUND!</h1>");} else {Class<?>[] parameterTypes = handler.getMethod().getParameterTypes();//定义一个参数的数组Object[] params = new Object[parameterTypes.length];for (int i = 0; i < parameterTypes.length; i++) {Class<?> parameterType = parameterTypes[i];if ("HttpServletRequest".equals(parameterType.getSimpleName())) {params[i] = req;} else if ("HttpServletResponse".equals(parameterType.getSimpleName())) {params[i] = resp;}}// 获取请求中的参数集合Map<String, String[]> parameterMap = req.getParameterMap();for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {String name = entry.getKey(); // "name"String value = entry.getValue()[0];  //  "bruce"int index = hasRequestParam(handler.getMethod(), name);if (index != -1) {params[index] = value;} else {// 不加@RequestParam的情况List<String> names = getParameterNames(handler.getMethod());System.out.println(names);for (int i = 0; i < names.size(); i++) {if (name.equals(names.get(i))) {params[i] = value;break;}}}}//调用控制中的方法Object result = handler.getMethod().invoke(handler.getController(), params);if (result instanceof String) {// 跳转jspString viewName = (String) result;if (viewName.contains(":")) {// forward:/user.jspString viewType = viewName.split(":")[0];String viewPage = viewName.split(":")[1];if (viewType.equals("forward")) {req.getRequestDispatcher(viewPage).forward(req, resp);} else {// redirect:/user.jspresp.sendRedirect(viewPage);}} else {// 默认就是转发req.getRequestDispatcher(viewName).forward(req, resp);}} else {// 返回JSON数据Method method = handler.getMethod();if (method.isAnnotationPresent(ResponseBody.class)) {ObjectMapper objectMapper = new ObjectMapper();String json = objectMapper.writeValueAsString(result);resp.setContentType("text/html;charset=utf-8");PrintWriter out = resp.getWriter();out.print(json);out.flush();out.close();}}}} catch (Exception e) {e.printStackTrace();}}/*** 获取请求对应的handler** @return*/public MyHandler getHandler(HttpServletRequest req) {String requestURI = req.getRequestURI();for (MyHandler myHandler : handlerList) {if (myHandler.getUrl().equals(requestURI)) {return myHandler;}}return null;}/*** 判断控制器方法的参数是否有RequestParm注解,且找到对应的value值** @param method* @param name* @return*/public int hasRequestParam(Method method, String name) {Parameter[] parameters = method.getParameters(); //method:public void com.bruce.controller.UserController.findUsersfor (int i = 0; i < parameters.length; i++) {Parameter p = parameters[i];boolean b = p.isAnnotationPresent(RequestParm.class);if (b) {RequestParm requestParm = p.getAnnotation(RequestParm.class);String requestParmValue = requestParm.value();if (name.equals(requestParmValue)) {return i;}}}return -1;}/*** 获取控制器方法的参数的名字** @param method* @return*/public List<String> getParameterNames(Method method) {List<String> list = new ArrayList<>();for (Parameter parameter : method.getParameters()) {String parameterName = parameter.getName();list.add(parameterName);}return list;}
}

com.springmvc.xml包:

XmlParser类:解析springmvc.xml文件

package com.springmvc.xml;import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import java.io.InputStream;/*** @Author: Juechen* @Date: 2024/4/24* @Description: 解析springmvc.xml文件* @Version: 1.0**/
public class XmlParser {public static String getbasePackage(String xml) {try {SAXReader saxReader = new SAXReader();// 获取XML文件的输入流InputStream inputStream = XmlParser.class.getClassLoader().getResourceAsStream(xml);// 使用SAXReader解析XML,并将结果存储在Document对象中Document document = saxReader.read(inputStream);// 获取XML文档的根元素Element rootElement = document.getRootElement();// 在根元素中查找名为"component-scan"的子元素Element element = rootElement.element("component-scan");// 获取"component-scan"元素的名为"base-package"的属性Attribute attribute = element.attribute("base-package");// 返回"base-package"属性的文本值,即要扫描的基础包名return attribute.getText();} catch (DocumentException e) {e.printStackTrace();}return "";}}

springmvc.xml文件:

<?xml version="1.0" encoding="UTF-8" ?>
<beans><!--设置使用注解的类所在的jar包--><component-scan base-package="com.bruce.service,com.bruce.controller"></component-scan>
</beans>

web.xml文件:

<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>Archetype Created Web Application</display-name><!--SpringMVC的核心控制器--><servlet><servlet-name>DispatcherServlet</servlet-name><servlet-class>com.springmvc.servlet.DispatcherServlet</servlet-class><!--SpringMVC的配置文件--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><!--Web服务器一旦启动,Servlet就会实例化创建对象,然后初始化--><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>DispatcherServlet</servlet-name><!--/表示所有请求都能被DispatcherServlet访问--><url-pattern>/</url-pattern></servlet-mapping></web-app>

user.jsp文件:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head><title>User.jsp</title>
</head>
<body><h1>${requestScope.message}</h1>
</body>
</html>

index.jsp文件(自动生成的):

<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

test


com.bruce.test包:

TestSpringMvc类:测试解析XML

package com.bruce.test;import com.springmvc.xml.XmlParser;
import org.junit.Test;/*** @Author: Juechen* @Date: 2024/4/24* @Description: TODO* @Version: 1.0**/
public class TestSpringMvc {@Testpublic void testreadXml() {String basePackage = XmlParser.getbasePackage("springmvc.xml");System.out.println(basePackage);}
}

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

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

相关文章

某知乎APP - X-Zse-96

⚠️前言⚠️ 本文仅用于学术交流。 学习探讨逆向知识&#xff0c;欢迎私信共享学习心得。 如有侵权&#xff0c;联系博主删除。 请勿商用&#xff0c;否则后果自负。 接口网址 app 版本: 8.10.0 aHR0cHM6Ly93d3cuemhpaHUuY29tL2FwaS92NC9zZWFyY2hfdjM 加密位置分析 > …

EOCRDS1T-05S反时限过电流保护继电器 施耐德韩国三和

三和EOCR株式会社是韩国zui大的电动机保护器生产企业&#xff0c;公司由金仁锡博士&#xff08;施耐德电气集团韩国*执行官&#xff09;于1981年建立。 2001年&#xff0c;为了把企业发展成性的、战略性企业&#xff0c;随后加入了法国施耐德电气集团公司。 EOCR主要产品有电…

YOLO新鲜腐烂水果检测数据集:8类,11000多张图像,标注完整

YOLO新鲜腐烂水果检测数据集&#xff1a;8类&#xff0c;11000多张图像&#xff0c;yolo标注完整&#xff0c;包含烂苹果&#xff0c;烂香蕉&#xff0c;烂橙子&#xff0c;烂石榴&#xff0c;好苹果&#xff0c;好香蕉&#xff0c;好橙子&#xff0c;好石榴8个类别 图像统一分…

<计算机网络自顶向下> Internet Protocol

互联网中的网络层 IP数据报格式 ver: 四个比特的版本号&#xff08;IPV4 0100, IPV6 0110&#xff09; headlen&#xff1a;head的长度&#xff08;头部长度字段&#xff08;IHL&#xff09;指定了头部的长度&#xff0c;以32位字&#xff08;4字节&#xff09;为单位计算。这…

OpenHarmony语言基础类库【@ohos.util.LightWeightMap (非线性容器LightWeightMap)】

LightWeightMap可用于存储具有关联关系的key-value键值对集合&#xff0c;存储元素中key值唯一&#xff0c;每个key对应一个value。 LightWeightMap依据泛型定义&#xff0c;采用轻量级结构&#xff0c;初始默认容量大小为8&#xff0c;每次扩容大小为原始容量的两倍。 集合中…

ElasticSearch语句中must,must_not,should 组合关系

前言&#xff1a; 在实际应用中&#xff0c;发现当bool中同时使用must和should 没有达到想要的想过&#xff0c;而是只展示了must中的命中数据&#xff0c;所以打算探究一下bool中 三种逻辑关系的组合。 上述查询语句只展示了must的结果&#xff0c;没有should中的结果&#…

OSPF的LSA详解

一、什么是LSA&#xff1f;LSA作用&#xff1f; 在OSPF协议中&#xff0c;LSA全称链路状态通告&#xff0c;主要由LSA头部信息&#xff08;LSA摘要&#xff09;和链路状态组成。部分LSA只有LSA头部信息&#xff0c;无链路状态信息。使用LSA来传递路由信息和拓扑信息&#xff0c…

HarmonyOS编程实践系列:第一节 - 创建健康App欢迎页

系列文章目录 &#xff08;零&#xff09;鸿蒙HarmonyOS入门&#xff1a;如何配置环境&#xff0c;输出“Hello World“ &#xff08;一&#xff09;鸿蒙HarmonyOS开发基础 &#xff08;二&#xff09;鸿蒙HarmonyOS主力开发语言ArkTS-基本语法 &#xff08;三&#xff09;鸿蒙…

STM32(垃圾桶开关盖)

封装超声波的代码 一、配置引脚的连接 二、配置 三、写代码 四、配置定时器 查找合适的定时器 其实这里的是remap&#xff08;复用&#xff09;&#xff0c;不重要 重要的是看Default才对 仔细查看之后发现还是能用的 先把开关灯封装好 再封装舵机 ----------------------…

IDEA更换新版本启动没反应

目前安装了新的IDEA(压缩包方式)&#xff0c;由于老版本的IDEA还在用&#xff0c;所以并没有删除&#xff0c;但是安装完后发现点击idea64.exe后没有反应&#xff0c;于是网上找了好多方法最后解决了 下面是我的解决过程 新版本&#xff1a;IntelliJIdea2024.1 老版本: Intelli…

智慧旅游引领旅游行业创新发展:借助智能科技的力量,推动旅游服务的个性化、精准化,提升游客的满意度和忠诚度

随着信息技术的迅猛发展和广泛应用&#xff0c;智慧旅游已成为旅游行业创新发展的重要引擎。智慧旅游借助智能科技的力量&#xff0c;推动旅游服务的个性化、精准化&#xff0c;不仅提升了游客的满意度和忠诚度&#xff0c;也为旅游行业的可持续发展注入了新的活力。本文将从智…

优化大型语言模型交互:提升查询和提示效果的26条原则

推荐下arxiv挂的一个提示词教程&#xff1a; https://github.com/VILA-Lab/ATLAS https://arxiv.org/abs/2312.16171 它提出了一套26条指导原则&#xff0c;改善和优化与大型语言模型&#xff08;LLMs&#xff09;的交互过程。通过这些原则&#xff0c;旨在简化对LLMs的查询和…

序列化与反序列化

【一】序列化跟反序列化 # api接口开发&#xff0c;最核心最常见的一个过程就是序列化&#xff0c;所谓序列化就是把数据转换格式&#xff0c;序列化可以分两个阶段&#xff1a;【序列化值的是转换数据格式&#xff1a;序列化&#xff0c;返序列化】# 序列化&#xff1a; 把我们…

如何安装sbt(sbt在ubuntu上的安装与配置)(有详细安装网站和图解)

sbt下载官网 选择对应的版本和安装程序 Download | sbt (scala-sbt.org) 安装 解压 将sbt-1.9.0.tgz上传到xshell&#xff0c;并解压 解压&#xff1a; tar -zxvf sbt-1.9.0.tgz 配置 1、在/home/hadoop/sbt中创建sbt脚本 /home/hadoop/sbt 注意要改成自己的地址 cd …

Quarto Dashboards 教程 3:Dashboard Data Display

「写在前面」 学习一个软件最好的方法就是啃它的官方文档。本着自己学习、分享他人的态度&#xff0c;分享官方文档的中文教程。软件可能随时更新&#xff0c;建议配合官方文档一起阅读。推荐先按顺序阅读往期内容&#xff1a; 1.quarto 教程 1&#xff1a;Hello, Quarto 2.qu…

vue3插槽的name和v-slot的研究

slot可以分为具名插槽和默认,默认插槽name是default 在父组件的template需要些v-slot/#,没写不生效,而在父组件下,而没被template包含的默认放在template且含有#default. 1)没写slot,可以不写template,也可写default的template2)写了name的slot,即使是default也必须些template…

linux开发板开机启动向日葵

硬件&#xff1a;orangepi 5 pro 操作系统&#xff1a;ubuntu 20.4 lts 安装向日葵 根据我的实测&#xff0c;arm架构的ubuntu系统只能安装向日葵提供的麒麟系统的那个版本&#xff0c;具体安装方式官网下载页面有 允许任意用户连接到 X11 使用root用户登录后打开终端输入一下…

JAVASE->数据结构|顺序表底层逻辑

✅作者简介&#xff1a;大家好&#xff0c;我是橘橙黄又青&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;再无B&#xff5e;U&#xff5e;G-CSDN博客 目标&#xff1a; 1. 什么是 List 2. List 常见接口介绍 3. …

python:reportlab 生成pdf:基本用法。

1.首先&#xff0c;打开cmd&#xff0c;安装reportlab pip install -i https://pypi.tuna.tsinghua.edu.cn/simple reportlab #从清华镜像安装更快 然后就可以使用其基本用法。 from reportlab.lib.pagesizes import letter from reportlab.pdfgen import canvasdef genera…

Swift - Playground

文章目录 Swift - Playground1. 新建Playground2. View3. 图片4. ViewController5. Playground - 多Page6. 注释6.1 Playground的注释支持markup语法&#xff08;与markdown相似&#xff09;6.1.1 语法 Swift - Playground Playground可以快速预览代码效果&#xff0c;是学习语…