一文了解SpringBoot

news2024/12/24 22:04:41

1 springboot介绍

1)springboot是什么?

Spring Boot是一个用于简化Java应用程序开发的框架。它基于Spring框架,继承了Spring框架原有的优秀特性,比如IOC、AOP等, 他并不是用来代替Spring的解决方案,而是和Spring框架紧密结合,进一步简化了Spring应用的整个搭建和开发过程通过自动配置约定优于配置的原则,提供了一种快速构建独立、可部署的Spring应用程序的方式。

Spring Boot减少了开发人员在配置上的工作量,使得开发者能够更专注于业务逻辑的实现。它还提供了丰富的功能和插件,可以轻松集成到各种开发环境和工具中。

再来详细解释一下,如果我们基于SSM框架进行过开发,我们可以理解,Spring在集成SpringMVC、Mybatis时,需要做大量的xml文件配置,在集成其他框架或中间件时,也是同样的道理。而再对比一下SpringBoot开发,我们可以发现,我们只需要引入不同的Starters的maven依赖,就可以开箱即用的进行开发。这就是SpringBoot为我们做的:提供默认的配置方式让我们更容易使用。

2)springboot的发展史

  • 2003年Rod Johnson成立Interface公司,产品是SpringFramework
  • 2004年,Spring框架开源,公司改名为Spring Source
  • 2008年,收购Apache Servlet、Tomcat,为SpringBoot内嵌Web容器奠定基础,整个生态自己掌握
  • 2009年,公司被VMWare以4.6亿美金收购被收购后,Spring公司接连收购了很多优秀的开源中间件,比如RabbitMQ、Redis
  • 2013年,VMWare、EMC、通用电气三者联合成立Pivotal公司,从这开始,Spring开始一路暴走
  • 2014年,推出SpringBoot1.0,基于Spring4.0开发
  • 2015年,推出SpringCloud
  • 2018年,Pivotal公司上市
  • 2018年3月,SpringBoot2.0发布,基于Spring5.0开发

3)为什么要用springboot

优点:

  • 快速构建一个独立的 Spring 应用程序 ;
  • 嵌入的 Tomcat 、 Jetty 或者 Undertow,无须部署 WAR 文件;
  • 提供starter POMs来简化Maven配置和减少版本冲突所带来的问题;
  • 对Spring和第三方库提供默认配置,也可修改默认值,简化框架配置;
  • 提供生产就绪型功能,如指标、健康检查和外部配置;
  • 无需配置XML,无代码生成,开箱即用;

![外

2 springboot的基本使用

1)springboot项目创建

a)快速创建

b)maven项目创建

2) spring的配置文件

a)默认配置文件

application.properties:

mydatasources.user-name=root
mydatasources.pass-word=123456
mydatasources.url=mysql:jdbc://127.0.0.1:3306/goods
mydatasources.map.aaa=123
mydatasources.map.bbb=222
mydatasources.map.ccc=333
mydatasources.student.sno=${server.port}

application.yml:

mydatasources:
    password: 123456
    username: root
    url: mysql:jdbc://127.0.0.1:3306/goods
    nums: 1,3,5,6,8,8,9

b)多环境下配置文件

​ 配置文件命名: application-{profile}.properties

​ 默认的配置文件中指定运行环境: spring.profiles.active=pro

​ profile的值和spring.profiles.active的值相同:

​ pro: 生产环境 dev: 开发环境 test: 测试环境

3)常用的注解

@SpringBootApplication: 这个注解标记一个主要的Spring Boot应用程序类。它组合了@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan三个注解,使得应用程序能够自动配置并扫描所需的组件;

@EnableAutoConfiguration: 开启springboot的自动配置;

@ComponentScan: 扫描指定路径下的类上的注解, 交给spring容器管理; 等于spring中xml文件的: context:component-scan/>

@Configuration注解; 声明该类是一个配置类;

@Bean注解: 往spring容器中注入bean, 对应的是spring中xml文件中的bean标签;

@ConfigurationProperties: 只要将类交给spring容器管理, 那么spring容器会自动去配置文件中读取对应的prefix + 属性的值, 封装到对应的属性中; 所以通常搭配, @bean注解或者@Conponent注解,或者@EnableConfigurationProperties注解使用;

在这里插入图片描述

出现以上警告, 导入对应依赖:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

同样是从配置文件中取值, 对比之前学过的@Value注解:

在这里插入图片描述

复杂类型数据的注入方式;

随机数以及${xx}的使用:

my.secret=${random.value}

my.number=${random.int}

my.bignumber=${random.long}

my.uuid=${random.uuid}

my.number.less.than.ten=${random.int(10)}

my.number.in.range=${random.int[1024,65536]}

app.name=MyApp
app.description=${app.name} is a Spring Boot application

@EnableConfigurationProperties: 可以将使用@ConfigurationProperties注解对应的类加入Spring容器;

​ 注意:@EnableConfigurationProperties与@Component不能同时使用

@PropertySource: 加载指定的非application.properties默认配置文件;

@profile 注解的作用是指定类或方法在特定的 Profile 环境生效,任何@Component或@Configuration注解的类都可以使用@Profile注解。在使用DI来依赖注入的时候,能够根据@profile标明的环境,将注入符合当前运行环境的相应的bean。

@ImportResource: 加载XML配置文件;

@ConditionalOn相关注解: 根据某些条件决定这个类或者这个方法是否交由spring的ioc去管理;

在这里插入图片描述

4)自动配置原理

1)运行启动类:

在这里插入图片描述

2)通过启动类上的注解, 开启自动配置

在这里插入图片描述

3)通过AutoConfigurationImportSelector,导入需要自动配置的类

在这里插入图片描述

AutoConfigurationImportSelector中的重要方法:
process方法()【在该方法中调getAutoConfigurationEntry()方法来得到自动配置类放入autoConfigurationEntry对象中】

      public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
   
		// 【1】deferredImportSelector强转为具体的AutoConfigurationImportSelector类型,
// 并调用getAutoConfigurationEntry方法得到自动配置类放入autoConfigurationEntry对象中
			AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
					.getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
 
//			【2】又将封装了自动配置类的autoConfigurationEntry对象撞见autoConfigurationEntries集合
			this.autoConfigurationEntries.add(autoConfigurationEntry);
 
//			【3】遍历刚刚获取的自动配置类
			for (String importClassName : autoConfigurationEntry.getConfigurations()) {
   
//				这里将符合条件的自动配置类作为key,annotationMetadata作为值存放金enrties集合
				this.entries.putIfAbsent(importClassName, annotationMetadata);
			}
          

        }

getAutoConfigurationEntry()方法

 protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
   

//       【1】得到spring.factories文件配置的所有的自动配置类
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
 
//		利用LinkedHashSet移除重复的配置类【不同的spring.factories中配置了相同的自动配置类】
		configurations = removeDuplicates(configurations);
 
//		得到要排除的自动配置类,比如注解属性exclude的配置类
//		比如:@SpringBootApplication(exclude= FreeMarkerAutoConfiguration.class)
//		将会获取到exclude = FreeMarkerAutoConfiguration.class的元注解数据
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
 
//		检查要被排除的配置类,因为有些不是自动配置类,故要抛出异常
		checkExcludedClasses(configurations, exclusions);
 
//		【2】将要排除的配置类移除
		configurations.removeAll(exclusions);
 
//		【3】因为从spring.factories文件获取的自动配置类太多。如果有些不必要的自动配置类都加载进内存,会造成内存浪费。
//		因此将一些不必要的配置类移除
		configurations = filter(configurations, autoConfigurationMetadata);
 
//		【4】获取了符合条件的自动配置类后,此时触发AutoConfigurationImportEvent事件
//		目的是告诉ConditionEvaluationReport条件评估报告器对象来记录符合条件的自动配置类
		fireAutoConfigurationImportEvents(configurations, exclusions);
 
//		【5】将符合条件和要排除的自动配置类封装进AutoConfigurationEntry对象
		return new AutoConfigurationEntry(configurations, exclusions);
     
    }

自动配置的入口方法: 调用了 process方法还有selectImport方法

在这里插入图片描述

process()方法上面已经详细讲解了,下面看一下selectImport()方法

selectImport()方法详解:

public Iterable<Entry> selectImports() {
   
			
//			这里得到所有要排除的自动配置类的set集合
			Set<String> allExclusions = this.autoConfigurationEntries.stream()
					.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
 
//			这里得到经过滤后符合条件的自动配置类的set集合
			Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
					.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
					.collect(Collectors.toCollection(LinkedHashSet::new));
 
//			移除掉要排除的自动配置类【exclude】
			processedConfigurations.removeAll(allExclusions);
 
//			将标有@Order注解的自动配置类进行排序
			return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
					.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
					.collect(Collectors.toList());
		}

下面我们以一个springboot帮我自动配置的类,进行演示:
使用过ssm框架的小伙伴们大概都有这样一个疑问,之前我们使用ssm框架的时候都要在web.xml文件中配置一个Filter用来处理post请求的乱码问题,但是使用springnboot却不会发生这种问题。

这是为什么呢?答案:因为springboot帮助我们自动配置了编码为UTF-8

HttpEncodingAutoConfiguration:这个类,用于帮助我们解决post请求的乱码问题。
HttpEncodingAutoConfiguration源码【详解】:

//表示这是一个配置类,和以前编写的配置文件一样,也可以给容器中添加组件
@Configuration(proxyBeanMethods = false)
 
//启动指定类【HttpProperties】的ConfigurationProperties功能:将配置文件中对应的值和HttpEncodingProperties绑定起来
@EnableConfigurationProperties(HttpProperties.class)
 
//spring底层@Conditional注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效。
//判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
 
//判断当前项目中有没有这个CharacterEncodingFilter:springmvc中解决乱码的乱码的过滤器
@ConditionalOnClass(CharacterEncodingFilter.class)
 
//判断配置文件中是否存在某个配置 spring.http.encoding.enabled   如果不存在,判断也是成立的
//matchIfMissing=true  表示即使我们配置文件中不配置spring.http.encoding.enabled=true  也是默认生效的
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
   
 
//	它已经和springboot配置文件中的值进行映射了
	private final HttpProperties.Encoding properties;
 
//	只有有参构造器的情况下,参数的值就会从容器中拿
	public HttpEncodingAutoConfiguration(HttpProperties properties) {
   
		this.properties = properties.getEncoding();
	}
 
	@Bean //给容器添加一个组件,这个组件中的某些值需要从properties中获取
	@ConditionalOnMissingBean //判断容器中有没有这个组件
	public CharacterEncodingFilter characterEncodingFilter() {
   
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
		return filter;
	}

5)项目部署

jar包的方式部署

​ a)添加Maven打包插件(不添加一定打包,但是找不到启动类和入口方法)

<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

​ b)使用IDEA开发工具进行打包

在这里插入图片描述

​ c)运行

​ java -jar *****.jar

war包方式部署

​ a)手动声明打包方式

<packaging>war</packaging>

​ b)声明使用外部的tomcat

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-tomcat</artifactId>
	<scope>provided</scope>
</dependency>

​ c)提供springboot启动的servlet初始化器

@ServletComponentScan 
@SpringBootApplication
public class Chapter05Application extends SpringBootServletInitializer {
   
     @Override
      protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
   
		return builder.sources(Chapter05Application.class);
	}
      public static void main(String[] args) {
   
		SpringApplication.run(Chapter05Application.class, args);
	}
}

​ d) 使用idea打包

​ e) 将打包的war包发布到tomcat上

6)单元测试

​ a)在pom文件中添加spring-boot-starter-test测试启动器

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
</dependency>

​ b)编写单元测试类

@RunWith(SpringRunner.class)     //加载spring相关的注解
@SpringBootTest                  //加载项目的上下文
public class App2 {
   
    
		@Autowired 
        private HelloController helloController;    //输入spring容器对象
    
        @Test
        public void helloControllerTest() {
   
            String hello = helloController.hello();
            System.out.println(hello);
        }    
}

7)springmvc功能扩展

​ 在Spring Boot项目中,一旦引入了Web依赖启动器spring-boot-starter-web,那么Spring Boot整合Spring MVC框架默认实现的一些XxxAutoConfiguration自动配置类就会自动生效,几乎可以在无任何额外配置的情况下进行Web开发。

​ 那么帮我们自动配置了哪些东西呢?

  1)  内置了两个视图解析器:ContentNegotiatingViewResolver和BeanNameViewResolver;
  2)  支持静态资源以及WebJars
  3)  自动注册了转换器和格式化器
  4)  支持Http消息转换器和消息代码解析器;
  5)  自动初始化Web数据绑定器ConfigurableWebBindingInitializer;
  6)  支持静态项目首页index.html
  7)  支持定制应用图标favicon.ico;

a) 注册视图控制器:

@Configuration
public class MyMVCconfig implements WebMvcConfigurer {
   
    
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
   
        registry.addViewController("/toLoginPage").setViewName("login");
        registry.addViewController("/login.html").setViewName("login");
    }
    
}

b)注册自定义拦截器,

实现HandlerInterceptor 接口,在该类中编写如下方法

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
   
    String uri = request.getRequestURI();
    Object loginUser = request.getSession().getAttribute("loginUser");
    if (uri.startsWith("/admin") && null == loginUser) {
   
        response.sendRedirect("/toLoginPage");
        return false;
    }
    return true;
}

在自定义配置类MyMVCconfig中,重写addInterceptors()方法注册自定义的拦截器

@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
   
	registry.addInterceptor(myInterceptor)
	             .addPathPatterns("/**")
                             .excludePathPatterns("/login.html");
}

c) 注册servlet

@Component
public class MyServlet extends HttpServlet {
   
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
		throws ServletException, IOException {
   
        		this.doPost(req, resp); }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
		throws ServletException, IOException {
   
       		 resp.getWriter().write("hello MyServlet");
  }}
@Configuration
public class ServletConfig {
   
    @Bean
    public ServletRegistrationBean getServlet(MyServlet myServlet){
   
        ServletRegistrationBean registrationBean = 
                                     new ServletRegistrationBean(myServlet,"/myServlet");
        return registrationBean;
    }
}

d) 注册过滤器

@Component
public class MyFilter implements Filter {
   
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
      }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                           FilterChain filterChain) throws IOException, ServletException {
   
        System.out.println("hello MyFilter");
        filterChain.doFilter(servletRequest,servletResponse);}
    @Override
    public void destroy() {
   }
}
@Bean
public FilterRegistrationBean getFilter(MyFilter filter){
   
	FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
	registrationBean.setUrlPatterns(Arrays.asList("/toLoginPage","/myFilter"));
	return registrationBean;
}

e)注册监听器

@Component
public class MyListener implements ServletContextListener {
   
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
   
        System.out.println("contextInitialized ..."); }
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
   
        System.out.println("contextDestroyed ...");  }
}

@Bean
public ServletListenerRegistrationBean getServletListener(MyListener myListener){
   
	ServletListenerRegistrationBean registrationBean = 
	new ServletListenerRegistrationBean(myListener);
	return registrationBean;
}

f) 使用路径扫描注册三大件

在对应组件上分别使用@WebServlet(“/annotationServlet”)注解来映射“/annotationServlet”请求的Servlet类,

使用@WebFilter(value = {“/antionLogin”,“/antionMyFilter”})注解来映射“/antionLogin”和“/antionMyFilter”请求的Filter类,

使用@WebListener注解来标注Listener类。

@WebServlet("/annotationServlet")
public class MyServlet extends HttpServlet {
   
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
                                         throws ServletException, IOException {
   
        			this.doPost(req, resp); }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                                          throws ServletException, IOException {
   
        			resp.getWriter().write("hello MyServlet"); }}
===================================================================

 @WebFilter(value = {
   "/antionLogin","/antionMyFilter"})
 public class MyFilter implements Filter {
   
     @Override
     public void init(FilterConfig filterConfig) throws ServletException {
      }
     @Override
     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                             FilterChain filterChain) throws IOException, ServletException {
   
         System.out.println("hello MyFilter");
         filterChain.doFilter(servletRequest,servletResponse);}
     @Override
     public void destroy() {
      } }
===================================================================

@WebListener
public class MyListener implements ServletContextListener {
   
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
   
        System.out.println("contextInitialized ..."); }
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
   
        System.out.println("contextDestroyed ..."); }
}
@SpringBootApplication
@ServletComponentScan  // 开启基于注解方式的Servlet组件扫描支持
public class Chapter05Application {
   
	public static void main(String[] args) {
   
		SpringApplication.run(Chapter05Application.class, args);
	}
}

3 thymeleaf视图

1)thymeleaf的配置

spring.thymeleaf.cache = true
spring.thymeleaf.encoding = UTF-8   
spring.thymeleaf.mode = HTML5   
spring.thymeleaf.prefix = classpath:/templates/    
spring.thymeleaf.suffix = .html   

2)thymeleaf的基本使用

ssm框架中已经学过

3)thymleaf国际化

a)准备国际化文件

login.properties, login_zh_CN.properties

login.tip=请登录
login.username=用户名
login.password=密码
login.rememberme=记住我
login.button=登录

login_en_US.properties

login.tip=Please sign in
login.username=Username
login.password=Password
login.rememberme=Remember me
login.button=Login

b) 配置国际化基础名

# 配置国际化文件基础名
spring.messages.basename=i18n.login

e) 定制区域化解析器

@Configuration
public class MyLocaleResovel implements LocaleResolver {
   

    @Override
    public Locale resolveLocale(HttpServletRequest httpServletRequest) {
   
        //获取请求的utl地址后拼接的l的值
        String l = httpServletRequest.getParameter("l");
        //获取到请求头中Accept-Language的值
        String header = httpServletRequest.getHeader("Accept-Language");
        Locale locale=null;
        //如果请求的url中带了l
        if(!StringUtils.isEmpty(l)){
   
            //使用_分割  第一个参数是语言  第二个参数是国家
            String[] split = l.split("_");
            locale=new Locale(split[0],split[1]);
        }else {
   
            //如果请求url地址中不带l 从请求头中分割出语言  和  国家
            String[] splits = header.split(",");
            String[] split = splits[0].split("-");
            locale=new Locale(split[0],split[1]);}
        return locale;
    }
    @Override
    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
   

    }
    @Bean
    public LocaleResolver localeResolver(){
   
        return new MyLocaleResovel();
    }
}

f)国际化页面 login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1,shrink-to-fit=no">
    <title>用户登录界面</title>
    <link th:href="@{/login/css/bootstrap.min.css}" rel="stylesheet">
    <link th:href="@{/login/css/signin.css}" rel="stylesheet">
</head>
<body class="text-center">
<!--  用户登录form表单 -->
<form class="form-signin">
    <img class="mb-4" th:src="@{/login/img/login.jpg}" width="72" height="72">
    <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">请登录</h1>
    <input type="text" class="form-control"
           th:placeholder="#{login.username}" required="" autofocus="">
    <input type="password" class="form-control"
           th:placeholder="#{login.password}" required="">
    <div class="checkbox mb-3">
        <label>
            <input type="checkbox" value="remember-me"> [[#{login.rememberme}]]
        </label>
    </div>
    <button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.button}">登录</button>
    <p class="mt-5 mb-3 text-muted">© <span th:text="${currentYear}">2018</span>-<span th:text="${currentYear}+1">2019</span></p>
    <a class="btn btn-sm" th:href="@{/login(l='zh_CN')}">中文</a>
    <a class="btn btn-sm" th:href="@{/login(l='en_US')}">English</a>
</form>
</body>
</html>

4)动态页面静态化

a)准备工作: 点击某个商品, 可以跳转到该商品对应的详情页面

b)修改controller中取到详情页面的控制器

 @GetMapping("/goods/{id}.html")
        public String goods(Model model,@PathVariable Integer id) throws Exception {
   
                //判断是否生成过该商品的静态页面
                if(!goodsService.isExists(id)){
     //如果没有生成  就直接去生成静态页面
                    Goods goods =   goodsService.createHTML(id);
                    model.addAttribute("goods",goods);
                    return "detail";
                }else {
     //如果已经生成过, 那么就直接返回静态页面
                        return id.toString();
         }
 }

​ c)使用模板引擎生成静态页面

thymeleaf.static.path=E:\\wsj\\springboot\\springboot-thymeleaf\\src\\main\\resources\\templates\\
    @Value("${thymeleaf.static.path}")
    private String htmlPath;
    
    @Autowired
    

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

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

相关文章

操作系统真象还原:内存管理系统

第8章-内存管理系统 这是一个网站有所有小节的代码实现&#xff0c;同时也包含了Bochs等文件 8.1 Makefile简介 8.1.1 Makefile是什么 8.1.2 makefile基本语法 make 给咱们提供了方法&#xff0c;可以在命令之前加个字符’&#xff20;’&#xff0c;这样就不会输出命令本身…

网络分析(ArcPy)

一.前言 GIS中的网络分析最重要的便是纠正拓扑关系&#xff0c;建立矫正好的网络数据集&#xff0c;再进行网络分析&#xff0c;一般大家都是鼠标在arcgis上点点点&#xff0c;今天说一下Arcpy来解决的方案&#xff0c;对python的要求并不高,具体api参数查询arcgis帮助文档即可…

Java_Map集合

认识Map集合 Map集合称为双列集合&#xff0c;格式&#xff1a;{key1value&#xff0c;key2value2,key3value3,…},一次需要存一对数据作为一个元素。 Map集合的每个元素“Keyvalue” 称为一个键值对/键值对对象/一个Entry对象&#xff0c;Map集合也被叫做“键值对集合” Map集…

Simscape Multibody与RigidBodyTree:机器人建模

RigidBodyTree&#xff1a;主要用于表示机器人刚体结构的动力学模型&#xff0c;重点关注机器人的几何结构、质量和力矩&#xff0c;以及它们如何随时间变化。它通常用于计算机器人的运动和受力情况。Simscape Multibody&#xff1a;作为Simscape的一个子模块&#xff0c;专门用…

10.2 Go Channel

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

虚拟机调用摄像头设备一直 select timeout问题的解决

在VMware里面调用v4l2-ctl捕获图像&#xff0c;或者opencv的VideoCapture(0)捕获图像&#xff0c;或者直接调用v4l2的函数&#xff0c;在streamon后&#xff0c;调用select读取数据&#xff0c;均会一直提示select timeout的问题&#xff0c;大概率是由于USB版本的兼容性造成的…

【氵】Archlinux+KDE Plasma 6+Wayland 安装nvidia驱动 / 开启HDR

参考: NVIDIA - Arch Linux 中文维基 &#xff08;其实就是把 wiki 简化了一下 注&#xff1a;本教程适用 GeForce 930 起、10 系至 20 系、 Quadro / Tesla / Tegra K-系列以及更新的显卡&#xff08;NV110 以及更新的显卡家族&#xff09;&#xff0c;此处以 RTX3060 为例 …

PHP 寿光蔬菜大棚宣传平台-计算机毕业设计源码88288

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于寿光蔬菜大棚宣传平台当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了寿光蔬菜大棚宣传平台&#xff0c;它彻底…

连续状态方程的离散化例子

连续状态方程的离散化 在控制系统中,连续状态方程的离散化是一个重要的步骤,用于将连续时间系统转换为离散时间系统,以便在数字控制器中实现。这通常涉及将连续时间的微分方程转换为离散时间的差分方程。常用的离散化方法 前向欧拉法(Forward Euler)简单易实现,但精度较…

详解python中的pandas.read_csv()函数

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 &#x1f913; 同时欢迎大家关注其他专栏&#xff0c;我将分享Web前后端开发、人工智能、机器学习、深…

OpenGL绘制简单图形

绘制了一个紫色矩形和一个三角形&#xff0c;代码如下&#xff1a; #include <Windows.h> #include <gl/glut.h> void display(void) {glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //设置清屏颜色glClear(GL_COLOR_BUFFER_BIT); //刷新颜色缓冲区&#xff1b;glColor3f…

“程序员职业素养全解析:技能、态度与价值观的融合“

文章目录 每日一句正能量前言专业精神专业精神的重要性技术执着追求的故事结论 沟通能力沟通能力的重要性团队合作意识实际工作中的沟通案例结论 持续学习持续学习的重要性学习方法进步经验结论 后记 每日一句正能量 梦不是为想象&#xff0c;而是让我们继续前往。 前言 在数字…

Policy-Based Reinforcement Learning(1)

之前提到过Discount Return&#xff1a; Action-value Function &#xff1a; State-value Function: &#xff08;这里将action A积分掉&#xff09;这里如果策略函数很好&#xff0c;就会很大&#xff1b;反之策略函数不好&#xff0c;就会很小。 对于离散类型&#xff1a; …

Qt中解决编译中文乱码和编译失败的问题

解决方法 1.使用#pragma execution_character_set(“utf-8”) QT5中在cpp中使用#pragma execution_character_set(“utf-8”)解决中文乱码&#xff0c;不过这里要求该源代码必须保存成带Bom的utf-8格式&#xff0c;这也是有些在网上下载的代码&#xff0c;加上这句源代码后还…

QPS,平均时延和并发数

我们当前有两个服务A和B&#xff0c;想要知道哪个服务的性能更好&#xff0c;该用什么指标来衡量呢&#xff1f; 1. 单次请求时延 一种最简单的方法就是使用同一请求体同时请求两个服务&#xff0c;性能越好的服务时延越短&#xff0c;即 R T 返回结果的时刻 − 发送请求的…

对猫毛过敏?怎么有效的缓解过敏症状,宠物空气净化器有用吗?

猫过敏是一种常见的过敏反应&#xff0c;由猫的皮屑、唾液或尿液中的蛋白质引起。这些蛋白质被称为过敏原&#xff0c;它们可以通过空气传播&#xff0c;被人体吸入后&#xff0c;会触发免疫系统的过度反应。猫过敏是宠物过敏中最常见的类型之一&#xff0c;对许多人来说&#…

C语言学习系列:初识C语言

前言&#xff0c;C语言是什么 语言&#xff0c;比如中文、英语、法语、德语等&#xff0c;是人与人交流的工具。 C语言也是语言&#xff0c;不过是一种特殊的语言&#xff0c;是人与计算机交流的工具。 为什么叫C语言呢&#xff1f; 这就要从C语言的历史说起了。 一&#…

11. MySQL 备份、恢复

文章目录 【 1. MySQL 备份类型 】【 2. 备份数据库 mysqldump 】2.1 备份单个数据表2.2 备份多个数据库2.3 备份所有数据库2.4 备份文件解析 【 3. 恢复数据库 mysql 】【 4. 导出表数据 OUTFILE 】【 5. 恢复表数据 INFILE 】 问题背景 尽管采取了一些管理措施来保证数据库的…

14. RTCP 协议

RTCP 协议概述 RTCP&#xff08;Real-time Transport Control Protocol 或 RTP Control Protocol 或简写 RTCP&#xff09;&#xff0c;实时传输控制协议&#xff0c;是实时传输协议&#xff08;RTP&#xff09;的一个姐妹协议。 注&#xff1a;RTP 协议和 RTP 控制协议&#…

Oracle数据库连接并访问Microsoft SQL Server数据库

Oracle数据库连接并访问Microsoft SQL Server数据库 说明&#xff1a;  1.实际开发中&#xff0c;Oracle数据库与SQLServer数据库之间可能需要相互进行访问&#xff0c;方便业务数据抽取&#xff0c;编写视图及表等操作。  2.SQLServer访问Oracle数据库配置相对较为简单&…