后端学习 - SpringBoot

  • SpringBoot 是整合 Spring 技术栈的一站式框架,是简化 Spring 技术栈的快速开发脚手架
  • 约定大于配置

文章目录

  • 一 概述
    • 1 第一个 SpringBoot 项目
    • 2 SpringBoot 特性:依赖管理
    • 3 SpringBoot 特性:自动配置
  • 二 SpringBoot 的 IOC容器
    • 1 组件添加:@Configuration
    • 2 组件添加:@Import
    • 3 组件添加:@Conditional
    • 4 引入原生配置文件:@ImportResource
    • 5 配置绑定:@ConfigurationProperties
    • 6 Lombok 的使用
  • 三 yaml 配置文件
    • 1 基本语法
    • 2 使用示例
    • 3 添加配置提示(自动补全)
  • 四 实例:后端管理系统
    • 1 静态资源的配置与访问
    • 2 配置控制器
    • 3 Thymeleaf 抽取页面的相同元素
    • 4 配置拦截器
    • 5 文件上传
    • 6 错误处理
  • 五 注入原生 Web 组件(Servlet,Filter,Listener)
    • 1 使用 Servlet API(推荐)
    • 2 使用 RegistrationBean
  • 六 数据访问
    • 1 导入 JDBC 场景
    • 2 切换 Druid 数据源
    • 3 整合 MyBatis
  • 七 单元测试
    • 1 JUnit5
    • 2 常用注解
    • 3 断言 assert
    • 4 假设 assumption
    • 5 嵌套测试
  • 八 指标监控
    • 1 开启方法
    • 2 常用端点


一 概述

1 第一个 SpringBoot 项目

  1. 导入 maven 依赖
    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.3</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>
  1. 创建主程序类,作为启动的入口,注意:启动类的目录一定要在 controller 等目录的至少上一级,或者在 @SpringBootApplication 注解中添加 scanBasePackages 属性
@SpringBootApplication(scanBasePackages = "controller")
public class HelloApplication {public static void main(String[] args) {SpringApplication.run(HelloApplication.class, args);}
}
  1. 创建控制器类以及控制器方法,@RestController = @ResponseBody + @Controller,用于标注控制器类,该控制器的 所有方法 向浏览器返回 控制器方法的返回值
@RestController  // @RestController = @ResponseBody + @Controller,向浏览器返回 该方法的返回值
public class HelloController {@RequestMapping("/hello")public String hello() {return "hello springboot";}
}
  1. 运行主程序类的 main 方法即可,无需更多配置

  2. 如果要修改某些配置,在 resources/application.properties 中修改即可,如:server.port=8888

  3. 如果要导出为 jar 包,需要在 maven 配置文件中添加:

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

并执行 maven 的 clean + package 操作
在这里插入图片描述

2 SpringBoot 特性:依赖管理

  • 自定义的 SpringBoot 项目的父项目 spring-boot-starter-parent,实现了依赖管理功能
  • 父项目的父项目 spring-boot-dependencies<properties> 标签声明了几乎所有开发中常用的依赖的版本号,实现自动版本仲裁机制(即:引入依赖默认可以不写版本,但是引入非版本仲裁的 jar,要写版本号)
  • 如果想使用依赖的指定版本,需要在当前项目的 maven 配置文件中的 <properties> 标签声明
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置<properties><mysql.version>5.1.43</mysql.version></properties>
  • 场景启动器:spring-boot-starter-*,只要引入 starter,这个场景的所有常规需要的依赖都进行自动引入;所有的启动器底层都依赖 SpringBoot 核心依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.6.3</version><scope>compile</scope>
</dependency>

3 SpringBoot 特性:自动配置

  • 主程序所在包及其下面的所有子包里面的组件(需要 @Component、@Controller… 注解才能称为组件,不加注解无法扫描)都会被默认扫描进来,不用显式地配置组件扫描
  • 各种配置拥有默认值,并按需加载所有自动配置项
  • 主程序类的注解 @SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan(主程序类所在包)
  • 自动配置流程:
    (Ⅰ) SpringBoot 加载所有的自动配置类xxxxxAutoConfiguration类,而非组件)
    (Ⅱ) 每个自动配置类按照条件生效,默认绑定配置文件指定的值(xxxxProperties类)
    (Ⅲ) 生效的配置类就会给容器中装配很多组件
    (Ⅳ) 如果要自定义配置,可以选择:创建 @Bean 替换底层组件,或修改组件获取的配置文件(这些文件最终都映射到 application.properties

二 SpringBoot 的 IOC容器

1 组件添加:@Configuration

  • @Configuration 注解的类,相当于原来的 xml 配置文件
  • 配置类本身也是组件
  • 向 IOC 容器中注入 Bean,对 @Configuration 类中的方法使用 @Bean 注解,将方法的返回对象注入容器
  • 默认情况下,注入容器的对象名为被注解的方法名,如果要修改则向 @Bean 中传递参数
@Configuration
class MyConfig {@Bean  // 根据方法的返回值,向IOC容器中注入对象,默认情况下的对象名为 jerrymousepublic Pet jerrymouse() {return new Pet("Jerry", 3);}
}
  • 代理 Bean 方法:@Configuration(proxyBeanMethod = true) 时(Full 模式),对于 @Bean 注解的方法,如果直接被调用,方法返回的对象是单例的;如果是 @Configuration(proxyBeanMethod = false) (Lite 模式)则非单例
  • Full / Lite 模式与组件依赖问题:
    配置的组件之间无依赖关系,用 Lite 模式,加速容器启动过程,减少判断
    配置类组件之间有依赖关系,用 Full 模式,组件单实例,保证依赖成立

2 组件添加:@Import

  • 对类进行的注解
  • 在 IOC 容器中创建组件,名字为类的全类名
@Import({User.class, Pet.class})
@Configuration(proxyBeanMethods = true)
public class MyConfig {
}

3 组件添加:@Conditional

  • 条件装配:满足指定的条件后进行组件装配,可以注解类和方法
  • 具有一系列的子注解,对应不同的情况
    @ConditionalOnBean(name="..."):IOC容器具有指定 Bean 时执行当前组件的装配
    @ConditionalOnMissingBean(name="..."):IOC容器失去指定 Bean 时执行当前组件的装配

4 引入原生配置文件:@ImportResource

  • 用于注解配置类,导入 Spring 的 xml 配置文件
  • 传递参数为配置文件的路径: @ImportResource("classpath:myspringconfig.xml")

5 配置绑定:@ConfigurationProperties

  • 目的是,使得 Java 读取到 properties 文件中的内容,并且把它封装到 JavaBean 中,以供随时修改并使用,即:JavaBean 和配置文件的绑定
  • @ConfigurationProperties 注解需要填入 prefix 属性,以在配置文件中指定其对象的属性值
@Component
@ConfigurationProperties(prefix = "jjjerry")
public class Pet {private String name;private int age;...
}// 在 application.properties 配置中:
// jjjerry.name="杰瑞"
// jjjerry.age=10
  • 如果是自定义类,在自定义类上注解 @ConfigurationProperties 即可;如果非自定义类,需要在配置类上额外注解 @EnableConfigurationProperties(Pet.class),它的作用是开启 Pet 的配置绑定功能,并将 Pet 组件自动注册到容器中

6 Lombok 的使用

  • 简化 Bean 的开发:
@Data  // 创建 getter、setter
@AllArgsConstructor  // 有参构造器
@NoArgsConstructor  // 无参构造器
@ToString  // ...
@EqualsAndHashCode  // ...
public class Person {private String name;private String address;
}
  • @Slf4j 简化日志记录,为注解的类注入了 log 实例:
@Slf4j
@SpringBootApplication
public class Application {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);log.info(String.valueOf(context.getBean("wubai").toString()));}
}@Configuration
class MyConfiguration {@Beanpublic Person wubai() {return new Person("wubai", "taipei");}
}

三 yaml 配置文件

  • 是一种面向数据的配置文件,推荐在配置组件属性时使用

1 基本语法

  1. 大小写敏感
  2. 使用缩进表示层级关系
  3. 缩进不允许使用tab,只允许空格
  4. 缩进的空格数不重要,只要相同层级的元素左对齐即可
  5. '#'表示注释
  6. 使用 key: value 的形式,注意其中的空格
  7. 字符串无需使用引号标注,使用引号时,单引号的转义字符不起作用,双引号起作用
  8. 详细的语法规则

2 使用示例

创建名为 wubai_wujunlin 的组件,并注入 IOC 容器:

@Component(value = "wubai_wujunlin")  // 组件在 IOC 容器中的名字
@ConfigurationProperties(prefix = "wujunlin")  // 组件在配置文件中的前缀
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public class Person {private String name;private String address;private List<String> bandMates;
}

依赖的 application.yaml

wujunlin:name: 吴俊霖address: 台北bandMates: [小朱, 大猫, Dino]

3 添加配置提示(自动补全)

在 maven 配置文件添加:

<!--添加自动补全功能--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional>
</dependency><!--打包时不包括自动补全--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId></exclude></excludes></configuration></plugin></plugins></build>

四 实例:后端管理系统

1 静态资源的配置与访问

  • 默认静态资源在 resources 目录下的 static 、public… 文件夹内
  • 访问时使用的路径:当前项目根路径/ + 静态资源名
  • 自定义访问静态资源使用的路径:
spring:mvc:static-path-pattern: "/custom_static_url/**"  
# 访问时: http://localhost:8080/custom_static_url/bf1.png
  • 欢迎页默认为静态资源路径下的 index.html
  • 输入地址 http://localhost:8080 即可访问欢迎页
  • 在静态资源目录下的 favicon.ico 同样会被自动解析

2 配置控制器

  • 为了避免刷新页面导致表单的重复提交,首次成功登陆后,在控制器方法中返回 "redirect:/main.html" 重定向到新的页面
@Controller
public class IndexController {@GetMapping(value = {"/login", "/"})public String loginPage() {return "login";}@PostMapping("/login")public String processLogin(User user, HttpSession session, Model model) {if (!user.getUsername().isEmpty() && !user.getPassword().isEmpty()) {  // 省略判断逻辑session.setAttribute("loginUser", user);return "redirect:/main.html";  // 使用重定向,防止表单的重复提交} else {model.addAttribute("msg", "账号密码错误");return "login";}}@GetMapping("/main.html")  // 直接访问 http://localhost:8080/main.html 仍然需要经过视图解析器才能获取main.html,而不能直接读取静态资源public String mainPage(HttpSession session, Model model) {if (session.getAttribute("loginUser") != null) {return "main";} else {model.addAttribute("msg", "未登录");return "login";}}
}

3 Thymeleaf 抽取页面的相同元素

官方文档对于 th:insert, th:replace, th:include 的示例

<body><div th:insert="footer :: copy"></div><div th:replace="footer :: copy"></div><div th:include="footer :: copy"></div></body>…will result in:
<body><div><footer>&copy; 2011 The Good Thymes Virtual Grocery</footer></div><footer>&copy; 2011 The Good Thymes Virtual Grocery</footer><div>&copy; 2011 The Good Thymes Virtual Grocery</div></body>

实现步骤

  1. 引入命名空间 <html lang="en" xmlns:th="http://www.thymeleaf.org">
  2. 创建公共部分的 html 页面,使用 th:fragmentid 为公共部分命名
1 使用 fragment 属性命名
<head th:fragment="commonheader"><meta charset="UTF-8"><title>表格页面的公共部分</title>...
</head>2 使用 id 属性命名
<div id="leftmenu" class="left-side sticky-left-side">...
</div>
  1. 导入公共部分:
1 对于 th:fragment 命名的标签,添加属性 th:xx(replace/insert/include)="公共文件名 :: fragment属性"
<div th:replace="common :: commonheader"></div>2 对于 id 命名的标签,添加属性 th:xx(replace/insert/include)="公共文件名 :: #id属性"
<div th:replace="common :: #leftmenu"></div>

4 配置拦截器

  • 拦截路径为 /** 时,静态资源的访问也会被拦截,需要为静态资源路径添加放行
  • 配置类:
@Configuration
public class MyConfig implements WebMvcConfigurer {// 配置拦截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**")  // 静态请求也会被拦截.excludePathPatterns("/", "/login", "/css/**", "/fonts/**", "/images/**", "/js/**");  // 放行不登陆就能访问的页面,和静态资源}
}
  • 拦截器的实现:
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {Object user = request.getAttribute("loginUser");if (user != null) {return true;} else {// 未登录,跳转到登录页// response.sendRedirect("/");  或:request.getRequestDispatcher("/").forward(request, response);log.warn("未登录!!");return false;}}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {//...HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//...HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}
}

在这里插入图片描述

5 文件上传

  1. html 的 from 标签
<form role="form" th:action="@{/upload}" method="post" enctype="multipart/form-data"><div class="form-group"><label for="exampleInputFile">上传单个文件</label><input type="file" name="singleImage" id="exampleInputFile1"></div><div class="form-group"><label for="exampleInputFile">上传多个文件,添加 multiple 属性</label><input type="file" name="multiImage" id="exampleInputFile2" multiple></div></form>
  1. 控制器方法
    使用 MultipartFile 参数类型获取上传文件,其方法 transferTo(...) 用于保存文件到服务器
    @PostMapping("/upload")public String upload(@RequestPart("headerImage") MultipartFile headerImg,@RequestPart("lifeImage") MultipartFile[] lifeImg) throws IOException {// 保存上传文件if (!headerImg.isEmpty()) {String fileName = headerImg.getOriginalFilename();headerImg.transferTo(new File("E:\\" + fileName));}// 多个文件用 for 循环上传// ...return "redirect:/main.html";}

6 错误处理

  • SpringBoot 默认的错误处理机制:error/下的4xx,5xx页面会被自动解析,发生错误时,有精确的错误状态码页面就匹配精确,没有就找 4xx / 5xx;如果都没有就触发白页
    在这里插入图片描述

五 注入原生 Web 组件(Servlet,Filter,Listener)

1 使用 Servlet API(推荐)

  • 使用 @WebServlet,@WebFilter,@WebListener 注解对应的类,并在启动类注解 @ServletComponentScan 传入 Web 组件位置
@WebServlet(urlPatterns = "/")
public class MyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//...}
}
@WebFilter(urlPatterns = {"/**"})
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("过滤器初始化");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("执行过滤操作");filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {System.out.println("过滤器销毁");}
}
@WebListener
public class MyListener implements ServletContextListener {@Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println("监听到项目初始化");}@Overridepublic void contextDestroyed(ServletContextEvent sce) {System.out.println("监听到项目销毁");}
}

2 使用 RegistrationBean

  • 无需注解
@Configuration
public class MyRegistConfig {@Beanpublic ServletRegistrationBean myServlet(){MyServlet myServlet = new MyServlet();return new ServletRegistrationBean(myServlet,"/my","/my02");}@Beanpublic FilterRegistrationBean myFilter(){MyFilter myFilter = new MyFilter();FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));return filterRegistrationBean;}@Beanpublic ServletListenerRegistrationBean myListener(){MySwervletContextListener mySwervletContextListener = new MySwervletContextListener();return new ServletListenerRegistrationBean(mySwervletContextListener);}
}

六 数据访问

1 导入 JDBC 场景

  • 创建项目时,在 Spring Initializer 中勾选 JDBC 即可
        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency>
  • 默认的数据源是 HikariDataSource
  • 常规配置
spring:datasource:driver-class-name: com.mysql.jdbc.Driverusername: rootpassword: 123url: jdbc:mysql://localhost:3306/test

2 切换 Druid 数据源

  • 引入依赖
        <dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version></dependency>
  • 配置示例
spring:datasource:driver-class-name: com.mysql.jdbc.Driverusername: rootpassword: 123url: jdbc:mysql://localhost:3306/testdruid:aop-patterns: com.atguigu.admin.*  #监控SpringBeanfilters: stat,wall     # 底层开启功能,stat(sql监控),wall(防火墙)stat-view-servlet:   # 配置监控页功能enabled: truelogin-username: adminlogin-password: adminresetEnable: falseweb-stat-filter:  # 监控webenabled: trueurlPattern: /*exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'filter:  # 配置开启的filterstat:    # 对上面filters里面的stat的详细配置slow-sql-millis: 1000logSlowSql: trueenabled: truewall:enabled: trueconfig:drop-table-allow: false

3 整合 MyBatis


七 单元测试

1 JUnit5

  • JUnit 5 = JUnit Platform(基础框架) + JUnit Jupiter(核心) + JUnit Vintage(向下兼容)
  • JUnit Platform: 在JVM上启动测试框架的基础,不仅支持Junit自制的测试引擎,其他测试引擎也都可以接入
  • JUnit Jupiter: JUnit Jupiter 提供了 JUnit5 的新的编程模型,是 JUnit5 新特性的核心。内部 包含了一个测试引擎,用于在Junit Platform上运行
  • JUnit Vintage: JUnit Vintage提供了兼容JUnit4.x,Junit3.x的测试引擎

2 常用注解

  • @Test :标注方法是测试方法
  • @ParameterizedTest:表示方法是参数化测试
  • @RepeatedTest:重复执行测试方法
  • @DisplayName:为测试类或者测试方法设置展示名称
  • @BeforeEach :在每个单元测试之前执行
  • @AfterEach :在每个单元测试之后执行
  • @BeforeAll :在所有单元测试之前执行,方法需要 static 修饰
  • @AfterAll :在所有单元测试之后执行,方法需要 static 修饰
  • @Tag :表示单元测试类别
  • @Disabled :不执行测试类或测试方法
  • @Timeout :测试方法运行如果超过了指定时间,将会返回错误
  • @ExtendWith :为测试类或测试方法提供扩展类引用

3 断言 assert

  1. 简单断言
方法说明
assertEquals判断两个对象或两个原始类型是否相等
assertEquals判断两个对象或两个原始类型是否相等
assertNotEquals判断两个对象或两个原始类型是否不相等
assertSame判断两个对象引用是否指向同一个对象
assertNotSame判断两个对象引用是否指向不同的对象
assertTrue判断给定的布尔值是否为 true
assertFalse判断给定的布尔值是否为 false
assertNull判断给定的对象引用是否为 null
assertNotNull判断给定的对象引用是否不为 null
  1. 数组断言
  • 通过 assertArrayEquals(...) 方法来判断两个对象或原始类型的数组是否相等
  • 对于对象类型数组,比较的方式是逻辑等于,即调用 equals 方法
@Test
@DisplayName("array assertion")
public void array() {assertArrayEquals(new int[]{1, 2}, new int[] {1, 2});
}
  1. 组合断言
  • 要求一系列断言同时满足
  • 使用 lambda 表达式提供方法实参(lambda 表达式对应函数式编程)
@Test
@DisplayName("assert all")
public void all() {assertAll("Math",() -> assertEquals(2, 1 + 1),() -> assertTrue(1 > 0));
}
  1. 异常断言
  • assertThrows 方法需要的参数:异常类型的 class 属性,需要抛出异常的语句的 lambda 表达式
@Test
@DisplayName("异常测试")
public void exceptionTest() {Assertions.assertThrows(ArithmeticException.class, () -> System.out.println(1 % 0));
}
  1. 超时断言
@Test
@DisplayName("超时测试")
public void timeoutTest() {Assertions.assertTimeout(Duration.ofMillis(1000), () -> Thread.sleep(500));
}
  1. 快速失败
@Test
@DisplayName("fail")
public void shouldFail() {fail("This should fail");
}

4 假设 assumption

  • 假设作为单元测试的前提条件,如果前提条件不满足则没有进行测试的必要
  • 不满足的断言会使得测试方法失败;不满足的前置条件只会使得测试方法的执行终止,而不会引起测试失败
  • assumeTrueassumFalse 确保给定的条件为 true 或 false,不满足条件会使得测试执行终止
  • assumingThat 的参数是表示条件的布尔值和对应的 Executable 接口的实现对象,只有条件满足时,Executable 对象才会被执行;当条件不满足时,测试执行并不会终止
@DisplayName("前置条件")
public class AssumptionsTest {private final String environment = "DEV";@Testpublic void simpleAssume() {assumeTrue(Objects.equals(this.environment, "DEV"));assumeFalse(() -> Objects.equals(this.environment, "PROD"));}@Testpublic void assumeThenDo() {assumingThat(Objects.equals(this.environment, "DEV"),() -> System.out.println("In DEV"));}
}

5 嵌套测试

  • 目的是将测试过程结构化,把相关的测试方法组织在一起
  • 对测试类及其内部类使用 @Nested 注解,实现嵌套测试
@DisplayName("A stack")
class TestingAStackDemo {Stack<Object> stack;// 最外层测试方法@Testvoid isInstantiatedWithNew() {new Stack<>();}// 嵌套第一层测试类@Nestedclass WhenNew {@BeforeEachvoid createNewStack() {stack = new Stack<>();}@Testvoid isEmpty() {assertTrue(stack.isEmpty());}// 嵌套第二层测试类@Nested@DisplayName("after pushing an element")class AfterPushing {String anElement = "an element";@BeforeEachvoid pushAnElement() {stack.push(anElement);}@Test@DisplayName("it is no longer empty")void isNotEmpty() {assertFalse(stack.isEmpty());}}}
}

八 指标监控

  • 微服务在云上部署以后,都需要对其进行监控、追踪、审计、控制等。SpringBoot 抽取了Actuator 场景,使得每个微服务可获得生产级别的应用监控、审计等功能

1 开启方法

  1. 引入场景依赖
        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
  1. 配置暴露端点(endpoint)及暴露方式
management:endpoints:enabled-by-default: true #暴露所有端点信息web:exposure:include: '*'  #以web方式暴露
  1. 访问 http://localhost:8080/actuator/... 监控对应指标

2 常用端点

  • Health:健康状况
  • Metrics:运行时指标
  • Loggers:日志记录

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

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

相关文章

centos rpm 安装 perl_Linux【常用软件安装篇】

摘要&#xff1a;本文介绍Linux常用的软件安装方式以及jdk、vim、mysql、tomcat、redis的安装过程。1 Linux常用软件安装方式常用方式有&#xff1a;rmp包安装、yum指令安装、源码包安装、解压免安装。1.1 rpm包安装rpm是Red-Hat Package Manager&#xff08;RPM软件包管理器&a…

日计不足涓滴成河-自定义响应结果格式化器

什么是响应结果响应结果就是&#xff0c;在客户端向服务器发出请求后&#xff0c;服务器根据客户端的请求参数&#xff0c;给出的结果&#xff0c;这就是一个完整的响应结果过程。响应的结果包含的内容非常多&#xff0c;主要的有 HTTP Status Code&#xff0c;Content-Type,Co…

docker 容器启动顺序_Docker容器启动时初始化Mysql数据库

1. 前言 Docker在开发中使用的越来越多了&#xff0c;最近搞了一个Spring Boot应用&#xff0c;为了方便部署将Mysql也放在Docker中运行。那么怎么初始化 SQL脚本以及数据呢&#xff1f; 我这里有两个传统方案。 第一种方案是在容器启动后手动导入&#xff0c;太low了不行。第二…

后端学习 - JVM(上)内存与垃圾回收

JVM 架构图 文章目录一 JVM 简介二 类加载子系统&#xff1a;1 作用2 类的三个加载过程3 类加载器的分类4 双亲委派机制 & Tomcat为何不遵循5 两个 class 对象为同一个类的必要条件三 运行时数据区&#xff1a;PC寄存器&#xff08;Program Counter Register&#xff09;四…

SM2 国密算法被 Linux 内核社区接受

喜欢就关注我们吧&#xff01;10 月 25 日&#xff0c;有开发者发文称&#xff0c;SM2 国密算法终于被 Linux 内核社区接受了。该作者表示&#xff0c;SM2 的补丁已经更新到了 v7 版本&#xff0c;这个版本的补丁最终被社区接受&#xff0c;目前已经合并到了 Linux 主线的 5.10…

后端学习 - MyBatis

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的 持久层框架 文章目录一 基于配置文件的 MyBatis 搭建1 搭建过程&#xff08;增删改&#xff09;2 查询操作3 特殊操作二 MyBatis 获取参数值的方式1 单个字面量类型的参数2 多个字面量类型的参数3 Map 类型的参数4 实体…

国产操作系统发展离不开人才和市场

日前&#xff0c;中国 1024 程序员节盛大举行&#xff0c;一大批开源大咖齐聚千年岳麓&#xff0c;围绕开源标准、生态、人才发展等主题分享&#xff0c;共议开源软件与操作系统未来。其中&#xff0c;统信软件总经理刘闻欢表示&#xff0c;“有了市场才会被真正的用起来”&…

后端学习 - Redis

文章目录一 Redis 概述Redis 为什么是单线程&#xff0c;单线程为什么这么快&#xff1f;数据存储结构二 常用数据类型1 String2 HashHash 的扩容机制&#xff1a;渐进式 rehash*3 List4 Set5 Zset三 Redis 事务1 乐观锁与 watch 命令2 事务的三个特性四 Redis 持久化1 RDB(Red…

再被补刀!Flash又遭抛弃,你会怀念它吗?

喜欢就关注我们吧&#xff01;微软近日发布通知&#xff0c;称更新了关于 Adobe Flash Player 的删除。微软更新目录站点可下载更新 KB4577586&#xff0c;用于删除 Flash Player。此更新适用于所有受支持的操作系统版本。重要版本 Windows 10 和 Windows 8.1 的可选更新也将在…

4位加法器的设计代码verilog_HDLBits:在线学习Verilog(六 · Problem 25-29)

本系列文章将和读者一起巡礼数字逻辑在线学习网站 HDLBits 的教程与习题&#xff0c;并附上解答和一些作者个人的理解&#xff0c;相信无论是想 7 分钟精通 Verilog&#xff0c;还是对 Verilog 和数电知识查漏补缺的同学&#xff0c;都能从中有所收获。附上传送门&#xff1a;M…

译 | 将数据从Cosmos DB迁移到本地JSON文件

点击上方蓝字关注“汪宇杰博客”原文&#xff1a;Azure Tips and Tricks翻译&#xff1a;汪宇杰在Cosmos DB中使用数据迁移工具有一项重复的任务是将数据从一种数据库格式迁移到另一种数据库格式。我最近使用Cosmos DB作为数据库来存储Ignite大会发出的所有推文。然而一旦获得了…

在线教育后端开发项目总结

文章目录一 数据库访问接口1 MyBatis2 Spring Data JPA3 Spring Data MongoDB二 数据库1 MySQL2 MongoDB3 Redis三 开发规范化、响应格式与异常处理1 开发规范2 响应格式3 异常处理四 RabbitMQ五 Spring Cloud 相关工具1 Eureka2 Ribbon3 Feign4 Zuul 网关六 搜索服务1 Elastic…

通讯故障_掌握PLC必备知识,人机界面和 PLC 出现通讯故障如何分析解决

此次主要在阐述人机界面和 PLC 通讯时的模式状态&#xff0c;并列举了通讯故障实例。帮助大伙加深对这俩者的了解&#xff0c;掌握起来也不再是难题&#xff0c;解决掉拦路虎。一 台数 显 四 辊 卷 板 机PLC 控 制 系 统 核 心 与 人机界面在使用过程中&#xff0c;出现人机界面…

后端学习 - 设计模式与设计原则

文章目录设计原则1 单一职责原则2 开闭原则3 Liskov 替换原则4 依赖倒置原则5 接口隔离原则6 迪米特法则设计模式&#xff1a;创建型模式1 工厂模式2 抽象工厂模式3 单例模式设计模式&#xff1a;行为型模式1 观察者模式2 模板模式3 备忘录模式设计模式&#xff1a;结构型模式1…

ai的预览模式切换_AI字体制作,用AI制作创意阶梯式文字

本篇教程通过AI制作一款创意阶梯式文字&#xff0c;教程中有很多知识点需要掌握&#xff0c;比如路径分割为网络&#xff0c;3D效果应用等&#xff0c;我们要利用他们创造出我们需要的文字出来&#xff0c;具体是如何制作的&#xff0c;我们通过教程一起来学习一下吧。效果图&a…

新版本 Swashbuckle swagger 组件中的 坑

新版本 Swashbuckle swagger 组件中的 Servers 坑Intro上周做了公司的项目升级&#xff0c;从 2.2 更新到 3.1&#xff0c; swagger 直接更新到了最新&#xff0c;swagger 用的组件是 Swashbuckle.AspNetCore&#xff0c;然后遇到一个 swagger 的问题&#xff0c; 在本地测试是…

后端学习 - MySQL存储引擎、索引与事务

文章目录一 存储引擎1 MyISAM 与 InnoDB 的差异二 索引1 主键索引与二级索引、索引覆盖、延迟关联2 聚簇索引与非聚簇索引3 数据结构3.1 哈希表3.2 B树3.3 B树3.4 跳表3.5 为什么不使用红黑树3.6 为什么不使用B树**4 索引下推 ICP **5 索引失效&#xff08;索引不命中&#xff…

. NET5正式版本月来袭,为什么说gRPC大有可为?

当前企业正在慢慢改用微服务架构来构建面向未来的应用程序&#xff0c;微服务使企业能够有效管理基础架构&#xff0c;轻松部署更新或改进&#xff0c;并帮助IT团队的创新和学习。它还可以帮助企业能够设计出可以轻松按需扩展的应用程序&#xff0c;此外&#xff0c;随着企业转…

后端学习 - 操作系统

文章目录一 基本概念1 操作系统的特征2 操作系统的位置3 计算机的硬件组成4 中断与异常5 系统调用二 进程管理1 进程控制块 PCB&#xff08;Process Control Block&#xff09;2 进程的状态与转换3 进程间的通信4 线程5 调度算法6 死锁7 PV 操作三 内存管理1 内存的非连续分配2…

西门子触摸屏脚本程序_通过驿唐PLC501远程下载Smart Line触摸屏

通过驿唐PLC-501远程下载Smart Line触摸屏一、触摸屏设置将PLC-501和Smart 700 IE V3通过网线连到一起。触摸屏上电后&#xff0c;点击Control Panel进入控制面板界面。进入控制面板后&#xff0c;点击Ethernet设置IP地址&#xff0c;与PLC-501联网宝在同一个网段。联网宝的IP地…