SpringBoot实战——个人博客项目

目录

一、项目简介

?二、项目整体架构

数据库模块

后端模块

前端模块

?三、项目具体展示

?四、项目的具体实现

1、一些准备工作

??数据库、数据表的创建

??设置数据库和MyBatis的配置

??将前端项目引入到当前项目中

2、登录注册模块

??实体类的创建

??前端后端交互

??后端流程

?? 登录功能的实现和注册大同小异

3、统一功能的处理

??统一异常处理

??统一数据格式返回

??统一用户的登录验证(用户登录拦截器)

??过程中遇到的bug

4、博客列表页面的实现(更新中…)

5、博客详情页面的实现

6、博客的修改和删除功能

7、博客列表分页功能的实现

8、随机加盐的实现


一、项目简介

项目名称:个人博客系统

主要操作的对象是:文章和用户,用户可在该系统上发表自己的博客,查看自己或别人已经发表的文章

需要用到两张表:userinfo(用户表)、articleinfo(文章表)

需要实现的功能:

登录+注册

博客的分页列表功能

新增发表博客

修改、删除自己的博客

项目技术栈

SSM(SpringBoot + SpringMVC + MyBatis)

MySQL

jQuery

项目亮点

手动对用户密码实现随机加盐

统一异常处理、拦截器

用户登录持久化(session内存)

分页功能

二、项目整体架构

数据库模块

两张表:用户表 + 文章表

后端模块

控制层(controller包)——》控制器

服务层(service包)——》服务类

持久层–数据访问层(java目录下mapper类 + resources目录下的mapper.xml)——》mapper

实体层(model包)——》实体类

工具层(config包+util包)——》统一异常处理、统一返回、随机加盐

前端模块

前端设计到7个页面

login.html登录页

reg.html注册页

blog_list.html总的博客列表页——》用到了blog_l

myblog_list.html个人博客列表页

blog_content.html博客详情页

blog_edit.html博客编辑页

blog_update.html博客修改页

三、项目具体展示

项目公网地址:登陆页面

登录页面、注册页面

总的博客列表页面

博客详情页

个人博客主页

博客修改页面

博客编辑页面

项目源码:java_spring: SpringMVC、SpringBoot、MyBatis学习 - Gitee.com

四、项目的具体实现

1、一些准备工作

首先我们新建一个springboot项目,项目具体的创建流程我这里就不在赘述。

详见:SpringBoot项目的创建

接下来我们就要数据库引入该项目。

??数据库、数据表的创建

用户表的创建

文章表的创建

??设置数据库和MyBatis的配置

??配置数据库的连接信息

这里的很多内容是固定的

# 数据库连接配置
Spring:
  datasource:
    url: jdbc:mysql://localhost:3306/你要连接的数据库名?characterEncoding=utf8&useSSL=false
    username: 用户名
    password: 自己的密码
    driver-class-name: com.mysql.cj.jdbc.Driver #只要你数据库用的是mysql这个是固定的

??配置MyBatis XML存放位置和命名规则

此时我们已经在通过maven将MySQL Driver和MyBatis Framework这两个包导入了进来,此时启动项目,项目依然能够正常运行,说明我们数据库连接是正常的。

??将前端项目引入到当前项目中

下面的前端的静态资源复制到我们resource/static目录下面:

springboot项目-个人博客系统静态页面[这里是图片018]https://download.csdn.net/download/weixin_61061381/87459276

2、登录注册模块

??实体类的创建

登录和注册不就是对用户表进行操作吗?这个我们首先创建用户表对应的实体类

首先根据我们数据库的表,在我们的程序中创建想对应的实体类——我们的MyBatis是ORM框架,我们的程序对象与关系数据库数据之间有响应的映射关系

  • 一个数据库中的数据表对应我们程序中的一个实体类
  • 数据表中的一行数据对应该实体类的一个实例化对象
  • 该数据表中的各个属性对应该实体类的成员变量(属性)

对了,还记我们springboot的扫描路径吗?

只有在启动类的同级目录下,springboot才会对该目录下的类进行扫描,配合类注解存到spring容器中。

接下来我们就尝试给我们的用户表插入一条数据。

如上图所示:我们从前端的login.html中获取到数据后,经过控制层——》服务层——》数据持久层,最后才作用到我们的数据库上。

废话不多说,让我们跟着流程来走一遍吧!

controller层

上图描述的是,我们通过url直接调用了我们控制层的sayHi()方法,并且把我们sayHi()方法返回的的结果展现在了浏览器上。

??但是现在我们有前端了,我们前端提交数据(调用我们的后端controller层的登录方法),然后把结果返回给前端不就行了吗(用户是登录失败了,还是成功了,交由我们的前端来处理)

??前端后端交互

首先用户在前端页面输入了用户信息

然后前端紧接着就把用户输入的信息传递给后端(提交到后端指定的接口上,比如登录提交的就是/user/reg

后端接收到用户信息,存到数据库中,并返回注册的结果(成功了?还是失败了?)

前端接受到后端返回的结果后做进一步的处理

??后端流程

还是先来看这张图

下面是根据上图流程构建的目录

controller层代码

package com.example.demo.controller;

import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
/**
 * 而Spring Boot框架项目接口返回 JSON格式的数据比较简单:
 * 在 Controller 类中使用@RestController注解即可返回 JSON格式的数据。
 */
@RestController
@RequestMapping("/user")
public class UserController {
    // 属性注入service服务层的userService类
    @Autowired
    public UserService userService;
    @RequestMapping("/reg")
    public HashMap<String, Object> reg(String username, String password1, String password2) {
        HashMap<String, Object> result = new HashMap<>();
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password1) || !StringUtils.hasLength(password2)) {
            result.put("status", -1);
            result.put("msg", "参数输入错误");
            result.put("data", "");
            return result;
        }
        else {
            if (!password1.equals(password2)) {
                result.put("status", -1);
                result.put("msg", "前后密码不一致");
                result.put("data", "");
                return result;
            }
            else {
                UserInfo userInfo = new UserInfo();
                userInfo.setUsername(username);
                userInfo.setPassword(password1);
                int ret = userService.reg(userInfo);
                if (ret != 1) {
                    result.put("status", -1);
                    result.put("msg", "数据库添加出错");
                    result.put("data", "");
                    return result;
                }
                else {
                    result.put("status", 200);
                    result.put("msg", "注册成功");
                    result.put("data", ret);
                    return result;
                }
            }
        }
    }
}

在controller层中调用了service服务层的reg方法

service服务层又调用了持久层中的mapper接口

mapper接口的实现:UserMapper.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
    <insert id="reg">
        insert into userinfo(username, password) values(#{userinfo.username}, #{userinfo.password});
    </insert>
</mapper>

到此,关于注册整个前后端的流程就走完了,下面我们来验证一下

但是当我们重复注册张三这个用户名

这个异常我们前端是不知道的,我们不知道发生了什么,是注册成功了?还是失败了?

在后端我们应该统一对异常进行处理,并把具体的异常情况告诉前端

这就是我们下面要说的统一处理功能的实现

关于前后端参数的传递,详见:SpringMVC学习笔记(获取参数,传递参数——关于前后端传参交互的总结、from表单、Ajax数据提交)_的博客-CSDN博客

关于MyBatis实现数据库的增删改查,详见:第一个MyBatis程序_的博客-CSDN博客

关于spring更简单的存取用户对象,详见:

spring更简单的对象存取

?? 登录功能的实现和注册大同小异

后端流程

前后端交互的流程

下面我们通过浏览器验证一下我们的登录功能

一点补充

通过controller层的代码,可以看到我们返回给前端的好像是hashmap,这样肯定是不行的。

这个时候就用到了我们的@RestController注解了

*@RestController是@Controller和@ResponseBody两者的结合,使用这个注解后该controller的所有方法都会返回json格式的数据

* 因为@ResponseBody的作用就是把返回的对象转换为json格式,并把json数据写入response的body中,前台收到response时就可以获取其body中的json数据了。
* 如果在整个controller类上方添加@RestController,其作用就相当于把该controller下的所有方法都加上@ResponseBody,使每个方法直接返回response对象

3、统一功能的处理

上面我们说了,当程序出现了异常获取其他情况,我们不统一处理(把结果告诉前端)我们其实是不知道发生了什么的。

??统一异常处理

所以我们需要单独在工具层中(我们的common包下面,建一个统一异常处理的类)

??统一数据格式返回

一般在web项目中,我们前后端都是通过json这种数据格式来交换数据格式——》我们后端需要给前端返回json格式的数据。

总之,我们前后端用户交互的数据个数一般是统一的,不会出现你一个接口用一种数据格式,而那个接口又换了,这样就会有很多问题,不利于开发。

统一数据的优点

  • 方便前端程序员更好的接受和解析后端数据接口返回的数据。
  • 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就可以了,因为所有接口都是这样返回的。
  • 有利于项目统一数据的维护和修改。
  • 有利于后端技术部门的统一规范的标准制定,不会出现稀奇古怪的返回内容。

统一数据格式的返回有两种实现方式,返回一个公共对象或者重写。

这里我们采用第二种重写(不过他的灵活性有待提升)

具体的我们可以使用@ControllerAdvice+ResponseBodyAdvice的方式实现,具体实现代码如下:

但是正如我们上面所说的,通过重写来进行统一数据格式的返回,他的灵活性的确有待提高。你看我们上面只是处理了成功的情况,但要是失败的情况呢?——》并且即使失败,也是分好几种情况呢!!!

我们不如再创建一个工具类,用来自定义返回hashmap数据(再通过@ResponseBody转成json格式)

那么对应的我们的统一数据格式返回类就发生了变化

package com.example.demo.common;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.HashMap;

/**
 * 统一数据格式返回(灵活性有待提高)
 *  通过统一数据格式的返回,不管我们控制层的方法返回了什么类型的数据
 *  通过重写末尾都能把他转成hashmap格式的数据,然后又通过@ResponseBody注解,将java对象转成了json对象。
 */
@ControllerAdvice
@ResponseBody
public class ResponseAdvice implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true; // 这个值为true的时候,才会对返回的数据进行重写
    }
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        // 在有了我们自定义数据返回后,我们的这个统一数据格式返回类就像是一个托地的。
        // 因为controller层可以直接调用AjaxResult,来返回hashmap(通过@ResponseBody转成json)
        // 但如果controller没有调用AjaxResult,直接返回了
        if (body instanceof HashMap) {
            return body;  // 此时已经是hashmap格式了
        }
        if (body instanceof Integer){ // 当controller层中的方法直接返回int类型时候
            int num = (int) body;
            if (num <= 0) {
                // 应对int类型错误返回(查询文章列表,新增和删除博客可能会用到)——》也可能用不到,如果新增或查询失败,我直接就在controller就返回了(通过调用AjaxResult)
                // 新增、删除或查询失败(非得在controller返回int值,再通过这里返回json对象的话,不灵活(出错信息显示的不具体
                // 所以说这里我们只是以防万一,我们还是选择再controller层直接返回json对象,这样更信息具体,更有怎针对性)
                return AjaxResult.fail("抱歉,本次操作失败,请稍后再试!"); // 这里无法区分是新增失败还是删除失败
                // 这里我们本来返回的是一个hashmap格式的对象,但加了@ResponseBody,把我们的java对象转成的了json格式
            }
        }

        if (body == null) { // (比如查询操作,直接返回查询到的UserInfo对象,然后直接返回该对象)
            // 这里我们本来返回的是一个hashmap格式的对象,但加了@ResponseBody,把我们的java对象转成的了json格式
            return AjaxResult.fail("抱歉,查询失败!"); // 这时对查询当前用户的特判
        }
        // 这里我们本来返回的是一个hashmap格式的对象,但加了@ResponseBody,把我们的java对象转成的了json格式
        return AjaxResult.success("操作成功", body);
        // 前端是通过result中的status值来判断操作是否成功的,这个类用来处理操作成功的情况(为操作成功的情况兜底)
        // 但这可能存在问题,如果操作失败,并且在controller层没有调用AjaxResult中的fail方法(而是直接返回,通过这个类来返回统一的数据格式,就会出现问题——》在这个类我们都是按成功的处理的)
        // 解决方案,在该类中提前判断body(判断操作失败的情况)--->我们约定如果操作失败就返回负数(在controller层调用AjaxResult的情况)
    }
}

那么与之对应的我们在controller层的类也就发生了改变

package com.example.demo.controller;

import com.example.demo.common.AjaxResult;
import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.jws.soap.SOAPBinding;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
/**
 * 而Spring Boot框架项目接口返回 JSON格式的数据比较简单:
 * 在 Controller 类中使用@RestController注解即可返回 JSON格式的数据。
 *  @RestController是@Controller和@ResponseBody两者的结合,使用这个注解后该controller的所有方法都会返回json格式的数据,
 *  因为@ResponseBody的作用就是把返回的对象转换为json格式,并把json数据写入response的body中,前台收到response时就可以获取其body中的json数据了。
 * 如果在整个controller类上方添加@RestController,其作用就相当于把该controller下的所有方法都加上@ResponseBody,使每个方法直接返回response对象。
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    public UserService userService;
    @RequestMapping("/reg")
    public Object reg(String username, String password1, String password2) {
        HashMap<String, Object> result = new HashMap<>();
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password1) || !StringUtils.hasLength(password2)) {

            return AjaxResult.fail("你输入的参数有误,请重新输入!");
        }
        else {
            if (!password1.equals(password2)) {
                return AjaxResult.fail("前后密码不一致,请重新输入!");
            }
            else {
                UserInfo userInfo = new UserInfo();
                userInfo.setUsername(username);
                userInfo.setPassword(password1);
                int ret = userService.reg(userInfo);
                if (ret != 1) {
                   return AjaxResult.fail("数据库添加用户失败,请稍后再试!");
                }
                else {
                    return AjaxResult.success("恭喜,注册成功!", ret);
                }
            }
        }
    }
    @RequestMapping("/login")
    public Object login(String username, String password) {
        HashMap<String, Object> result = new HashMap<>();
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
            return AjaxResult.fail("你输入的参数有误,请重新输入!");
        }
        else {
            // 需要在数据库中查询当前登录的用户是否存在
            UserInfo userInfo = userService.selectByUsername(username);
            if (userInfo == null || !password.equals(userInfo.getPassword())) {
               return AjaxResult.fail("你当前的用户名或密码错误,请重新输入!");
            }
            else  {
                return AjaxResult.success("恭喜,登录成功!", "");
            }
        }
    }
}
??统一用户的登录验证(用户登录拦截器)

spring拦截器

对于以上问题Spring中提供了具体的实现拦截器:HandlerInterceptor,拦截器的实现分为以下两个步骤:

1、创建自定义拦截器,实现 HandlerInterceptor 接口的perHandle(执行具体方法之前的预处理)方法。

2、将自定义拦截器加入 WebMvcConfiger的 addInterceptors方法中。

创建用户登录拦截器

将该自定义拦截器放到系统的配置文件中

(将自定义拦截器加入 WebMvcConfiger的 addInterceptors方法中)

用浏览器测试一下是否真的拦截了

可以看到因为我们没有放行login.html,登录页面直接显示不出来了。

我们改下拦截规则

然后你发现,咦,怎么还是不行。

当然不行呀,你虽然运行了login.html通行,但是login.html还用到了css/js/image图片呢!这些东西你还没放行呢!!!

??过程中遇到的bug

一开始,当我把自定义的用户登录拦截器放到了系统配置文件,我欢欢喜喜的启动项目,结果——

加上类注解后问题就解决了。

关于统一功能的处理,详见:SpringBoot统一功能处理_的博客-CSDN博客

4、博客列表页面的实现(更新中…)

5、博客详情页面的实现

6、博客的修改和删除功能

7、博客列表分页功能的实现

8、随机加盐的实现

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

利用sda剩余空间,扩容(lvm)

r如果余空间没有使用&#xff0c;直接扩容 pvdisplay vgdisplay pvresize /dev/sda3 扩展逻辑卷的大小&#xff1a; lvextend -l 100%FREE /dev/mapper/openeuler-root 对于ext4文件系统&#xff1a; resize2fs /dev/mapper/vg_openeuler-openeuler--root 对于xfs文件系…

【Golang】Go语言编程思想(一):接口

接口 接口的概念 现在我们要实现一个函数&#xff0c;用于对给定的 url 进行解析&#xff0c;具体的代码实现如下&#xff1a; package mainimport ("fmt""io""net/http" )func retrieve(url string) string {resp, err : http.Get(url)if er…

智能文档解析综述:结构化信息提取的技术、挑战与前景

综述论文&#xff1a;https://arxiv.org/abs/2410.21169 摘要 文档解析对于将非结构化和半结构化文档&#xff08;如合同、学术论文和发票&#xff09;转换为结构化、机器可读的数据至关重要。通过从非结构化输入中提取可靠的结构化数据&#xff0c;文档解析为众多应用提供了极…

如何将CSDN博客下载为PDF文件

1.打开CSDN文章内容 2.按键盘上的f12键&#xff08;或者右键—审查元素&#xff09;进入浏览器调试模式&#xff0c;点击控制台&#xff08;Console&#xff09;进入控制台 3.在控制台输入以下代码&#xff0c;回车 4.在弹出的打印页面中将布局设置成横向&#xff0c;纵向会…

C# GDI绘制的小熊进度条

C# GDI小熊进度条 1、添加自定义控件winform using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;…

嵌入式入门Day25

数据结构Day 6,IO Day1 查找算法顺序查找折半查找&#xff08;二分查找&#xff09;哈希查找 IO概念标准IO创建递归索引&#xff08;用于查询结构体定义&#xff09; 文件IO标准IO缓冲区指针相关函数 查找算法 顺序查找 关键字&#xff1a;分为主关键字和次关键字主关键字&am…

操作系统——虚拟内存管理

笔记内容及图片整理自XJTUSE “操作系统” 课程ppt&#xff0c;仅供学习交流使用&#xff0c;谢谢。 背景 进程必须全部放入物理内存后方可运行&#xff0c;这个规则将程序大小限制为物理内存大小。许多情况下并不需要将整个程序置于内存中&#xff0c;比如程序几乎从不执行但…

Java 在Json对象字符串中查找和提取特定的数据

1、在处理JSON数据时&#xff0c;需要提出个别字段的值&#xff0c;通过正则表达式提取特定的数据 public static void main(String[] args) {//定义多个JSON对象字符串类型&#xff0c;假设每个对象有a,b,c 字段String strJson "{\"a\":1.23,\"b\"…

进度与预算

一个项目&#xff0c;如果进度上可以按时完成&#xff0c;一般来说预算不会超标&#xff0c;或者超标幅度有限。 一个项目&#xff0c;如果进度上严重超期&#xff0c;预算基本上会超标&#xff0c;而且超标很大。 现在很多项目&#xff0c;人力成本占比都比较大&#xff0c…

Ungoogled Chromium127编译指南 Windows篇 - 安装Visual Studio 2022(六)

1. 引言 在编译Ungoogled Chromium之前&#xff0c;正确安装和配置Visual Studio 2022是至关重要的一步。作为主要的开发环境&#xff0c;Visual Studio不仅提供了必要的编译工具&#xff0c;还包含了大量构建过程中需要的组件和库。本文将详细介绍如何在Windows系统上安装和配…

电子商务人工智能指南 3/6 - 聊天机器人和客户服务

介绍 81% 的零售业高管表示&#xff0c; AI 至少在其组织中发挥了中等至完全的作用。然而&#xff0c;78% 的受访零售业高管表示&#xff0c;很难跟上不断发展的 AI 格局。 近年来&#xff0c;电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…

精确的单向延迟测量:使用普通硬件和软件

论文标题&#xff1a;Precise One-way Delay Measurement with Common Hardware and Software&#xff08;精确的单向延迟测量&#xff1a;使用普通硬件和软件&#xff09; 作者信息&#xff1a;Maciej Muehleisen 和 Mazen Abdel Latif&#xff0c;来自Ericsson Research Eri…

字符串的特征

底层是char类型的数组 char[] replace()&#xff1a;替换 split()&#xff1a;切分 indexOf()&#xff1a;第一个字符所在位置&#xff0c;从0开始算 substring(3, 6)&#xff1a;字符串截取&#xff0c;包括3不包括6 字符串不可变 本质上是数组&#xff0c;数组是固定值…

三维扫描检测在汽车制造中的应用

三维扫描&#xff0c;通过先进三维扫描技术获取产品和物体的形面三维数据&#xff0c;建立实物的三维图档&#xff0c;满足各种实物3D模型数据获取、三维数字化展示、3D多媒体开发、三维数字化存档、逆向设计、产品开发、直接3D打印制造或辅助加工制造等一系列的应用。 三维扫描…

【已解决】黑马点评项目中启动Spring Boot服务失败,com.sun.tools.javac.tree.JCTree qualid

黑马点评项目中启动Spring Boot服务失败 报错提示 java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field com.sun.tools.javac.tree.JCTree qualid这是因为 lombok 版本不兼容造成的 找到 pom.xml 文件&#xff0…

Netty入门(快速了解以及使用netty)

二. Netty 入门 1. 概述 1.1 Netty 是什么&#xff1f; Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.Netty 是一个异步的、基于事件驱动的网络应用框架&…

Python办公—DataMatrix二维条码制作

目录 专栏导读1、库的介绍2、库的安装3、核心代码4、完整代码总结专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️‍🌈 博客主页:请点击——> 一晌小贪欢的博客主页求关注 👍 该系列文章专栏:请点击——>Python办公自动化专…

前缀和(八)矩阵区域和

1314. 矩阵区域和 给你一个 m x n 的矩阵 mat 和一个整数 k &#xff0c;请你返回一个矩阵 answer &#xff0c;其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和&#xff1a; i - k < r < i k, j - k < c < j k 且(r, c) 在矩阵内。 示例 1&…

Nginx日常运维方法Linux版

关注 工 仲 好&#xff1a;IT运维大本营1&#xff0c;安装&#xff1f; 下载RPM&#xff1a;wget http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.10.0-1.el7.ngx.x86_64.rpm 离线包用其它方式下载也可以。 安装&#xff1a;rpm -ivh nginx-1.10.0-1.el7.ngx.x86_…

基于eFramework车控车设中间件介绍

车设的发展&#xff0c;起源于汽车工业萌芽之初&#xff0c;经历了机械式操作的原始粗犷&#xff0c;到电子式调控技术的巨大飞跃&#xff0c;到如今智能化座舱普及&#xff0c;远程车控已然成为汽车标配&#xff0c;车设功能选项也呈现出爆发式增长&#xff0c;渐趋多元繁杂。…