------web 开发登录功能------

  修改login.html文件:注意加粗部分为 msg 字符串不为空时候 才进行显示

<!DOCTYPE html>
<!-- saved from url=(0050)http://getbootstrap.com/docs/4.0/examples/sign-in/ -->
<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">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="http://getbootstrap.com/favicon.ico"> <title>Signin Template for Bootstrap</title> <!-- Bootstrap core CSS -->
<link href="/asserts/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/4.0.0/css/bootstrap.css}" rel="stylesheet"> <!-- Custom styles for this template -->
<link href="/asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">
</head> <body class="text-center">
<form class="form-signin" th:action="@{/user/login}" method="post">
<img class="mb-4" src="/asserts/img/bootstrap-solid.svg" th:src="@{/asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72">
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<p style="color: red;" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
<label for="username" class="sr-only" th:text="#{login.username}">Email address</label>
<input name="username" type="email" id="username" th:placeholder="#{login.username}" class="form-control" placeholder="Email address" required="" autofocus="">
<label for="inputPassword" th:text="#{login.password}" class="sr-only">Password</label>
<input name="password" type="password" th:placeholder="#{login.password}" id="inputPassword" class="form-control" placeholder="Password" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"/> [[#{login.remember}]]
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
</form>
</body></html>

  添加一个controller 对应页面跳转

package com.lixuchun.springboot.controller;

import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam; import java.util.Map; @Controller
public class LoginController { // @RequestMapping(value = "/user/login", method = RequestMethod.POST)
@PostMapping(value = "/user/login")
public String login(@RequestParam String username, @RequestParam String password
,Map<String, Object> map) {
if (!StringUtils.isEmpty(username) && "123456".equals(password)) {
// 登录成功
return "dashboard";
} else {
map.put("msg", "用户登录失败!");
// 登录失败
return "login";
}
}
}

  实现效果:填写正确情况下跳转到 dashboard.html页面中,错误情况下 返回login页面 并且显示 用户登录失败!

  登录 开发期间模板引擎页面修改以后要实时生效

    禁用模板引擎缓存:spring.thymeleaf.cache=false

    修改页面完成以后 ctrl + f9 重新编译

  当页面位于 dashboard 页面 按 F5 会有是否表单再次提交提示 (表单重复提交)

    可以进行重定向防止重复提交

     if (!StringUtils.isEmpty(username) && "123456".equals(password)) {
// 登录成功
// 防止表单从夫提交 可以从定向导主页
return "redirect:/main.html";
} else {
map.put("msg", "用户登录失败!");
// 登录失败
return "login";
}

    修改Mvc View视图解析器

    @Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter() {
WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
registry.addViewController("/main.html").setViewName("dashboard");
}
};
return adapter;
}

  如果这样修改了 直接访问 localhost:8080/main.html 就可以直接访问 登录功能没起到作用 那么引入拦截器

  拦截器 编写拦截器controller 必须实现 HandlerInterceptor

  pre 在登录之前进行检查:

package com.lixuchun.springboot.component;

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* 进行登录检查
*/
public class LoginHandlerIntercepter implements HandlerInterceptor{ // 目标方法预检查
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object user = request.getSession().getAttribute("loginUser");
if (user == null) {
// 未登录 返回登录页面
request.setAttribute("msg", "没有用户权限 请先登录");
       // 没有登录跳转到 /index.html 页面
request.getRequestDispatcher("/index.html").forward(request, response);
return false;
} else {
// 已经登录 放行请求
return true;
}
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { }
}

  Mvc 配置文件添加 Interceptor 组件 进行注册:

    @Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter() {
WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
registry.addViewController("/main.html").setViewName("dashboard");
} // 注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 拦截任意请求
// 已经做好了静态资源的映射 *.css *.js 访问等 不需要做处理
registry.addInterceptor(new LoginHandlerIntercepter()).addPathPatterns("/**")
.excludePathPatterns("/index.html", "/", "/user/login");
}
};
return adapter;
}

  访问效果:在没有登录的情况下 访问 localhost:8080/main.html

  登录后再次访问:左侧上面 test@test.com 为登录名称 dashboard 页面 [[${session.loginUser}]] 行内表达式取值

  CRUD-员工列表

  实验要求:

    1) RestfulCRUD: CRUD 满足Rest风格

    URI : /资源名称/资源标识  HTTP请求方式区分对资源的CRUD操作

       /emp/{id}

    

    2). 实验的请求架构

    

    

    3).员工列表

      抽取公共元素片段

        <div th:fragment="copy">&COPY 2011 thymes Virtual Grocery</div>

      引入公共元素片段

        <div th:insert="~{footer::copy}"></div>

        ~{templatename::selector} :模板名 :: 选择器

        ~{templatename::fragmentname}:模板名::片段名

      三种引入公共片段th属性:

        th:insert :将公共的片段整个插入到声明引用的div中

        th:replace: 将声明引入的元素替换为公共片段

        th:include:被引入的片段内容包含近这个标签中

        如果使用th:insert 等属性进行引入 可以不用写 ~{}

        行内写法加上 [[~{}]] , [(~{})] (转义不转义)

      dashboard 页面定义公共片段头 th:fragment="topbar"

<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">[[${session.loginUser}]]</a>
<input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
</li>
</ul>
</nav>

      list 页面头取法

<!-- 引入抽取的topbar -->
<!-- 模板名称:使用thymeleaf的配置规则进行解析 -->
<div th:replace="~{dashboard::topbar}"></div>

      dashboard 页面定义公共片段侧边栏 id="sideBar"

    <nav id="sideBar" class="col-md-2 d-none d-md-block bg-light sidebar" style="margin-top: 50px;">
<div class="sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
Dashboard <span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
Orders
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shopping-cart"><circle cx="9" cy="21" r="1"></circle><circle cx="20" cy="21" r="1"></circle><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path></svg>
Products
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" th:href="@{/emps}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>
员工管理
</a>
</li>
</ul>
</div>
</nav>

      list 页面侧边栏取法

<!-- 引入侧边栏 -->
<div th:replace="~{dashboard::#sideBar}"></div>

    也可以单独提出一个bar文件 然后在各个页面进行调用

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- top bar -->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">[[${session.loginUser}]]</a>
<input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
</li>
</ul>
</nav> <!-- side bar -->
<nav id="sideBar" class="col-md-2 d-none d-md-block bg-light sidebar" style="margin-top: 50px;">
<div class="sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shopping-cart"><circle cx="9" cy="21" r="1"></circle><circle cx="20" cy="21" r="1"></circle><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path></svg>
Products
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" th:href="@{/emps}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>
员工管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-layers"><polygon points="12 2 2 7 12 12 22 7 12 2"></polygon><polyline points="2 17 12 22 22 17"></polyline><polyline points="2 12 12 17 22 12"></polyline></svg>
Integrations
</a>
</li>
</ul>
</div>
</nav>
</body>
</html>

    页面进行调用 list 页面 效果和之前的效果一样

<!-- 引入抽取的topbar -->
<!-- 模板名称:使用thymeleaf的配置规则进行解析 -->
<div th:replace="commons/bar::topbar"></div>
<!-- 引入侧边栏 -->
<div th:replace="commons/bar::#sideBar"></div>

    

  引入片段也可以传入参数:

    在 dashboard.html 页面引入左侧栏时候 传入参数

<div th:replace="commons/bar::#sideBar(activeUri='main.html')"></div>

    在 bar.html 页面设置左侧栏时候 通过传过来的参数设置 是否高亮

<li class="nav-item">
  <a class="nav-link active" href="#"
  th:href="@{/main.html}" th:class="${activeUri=='main.html'?'nav-link active':'nav-link'}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
  Dashboard <span class="sr-only">(current)</span>
</a>
</li>

   

  员工列表做数据展示:

  list.html 页面编写

    <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
      <div class="chartjs-size-monitor" style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: hidden; pointer-events: none; visibility: hidden; z-index: -1;">
        <div class="chartjs-size-monitor-expand" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;">
        <div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div>
        </div>
          <div class="chartjs-size-monitor-shrink" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;">
            <div style="position:absolute;width:200%;height:200%;left:0; top:0">
          </div>
        </div>
      </div>
<h2><button class="btn btn-sm btn-success">员工添加</button></h2>
<h2>Section title</h2>
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>#</th>
<th>lastName</th>
<th>email</th>
<th>gender</th>
<th>department</th>
<th>birth</th>
<th>options</th>
</tr>
</thead>
<tbody>
<tr th:each="emp:${emps}">
<td th:text="${emp.id}"></td>
<td>[[${emp.lastName}]]</td>
<td th:text="${emp.email}"></td>
<td th:text="${emp.gender}==0?'girl':'boy'"></td>
<td th:text="${emp.department.departmentName}"></td>
<td th:text="${#dates.format(emp.birth, 'yyyy-MM-dd HH:mm')}"></td>
<td>
<button class="btn btn-sm btn-primary">编辑员工</button>
<button class="btn btn-sm btn-danger">删除员工</button>
</td>
</tr>
</tbody>
</table>
</div>
</main>

  做一个伪处理 employeeDao

package com.lixuchun.springboot.dao;

import com.lixuchun.springboot.entities.Department;
import com.lixuchun.springboot.entities.Employee;
import org.springframework.stereotype.Repository; import java.util.ArrayList;
import java.util.Date;
import java.util.List; @Repository
public class EmployeeDao {
public Employee selectEmpById(Integer id) {
return new Employee();
} public List<Employee> selectEmps() {
List<Employee> empList = new ArrayList<Employee>();
for (int i = 0; i < 6; i++) {
Employee emp = new Employee(i, "emp" + i,
i + "emp@emp.com", 0,
new Department(i, "dep"+ i), new Date());
empList.add(emp);
}
return empList;
}
}

  employee / department

department
private Integer id;
private String departmentName; employee
id
lastName
email
gender
department
birth

  EmpController 编写

    @Autowired
EmployeeDao employeeDao; // 查询所有员工返回列表页面
@GetMapping("/emps")
public String list(Model model) {
List<Employee> employees = employeeDao.selectEmps();
model.addAttribute("emps", employees);
// classpath:/templates/xxx.html
return "emp/list";
}

  最后页面效果:

  员工添加功能:

    list 添加按钮  <a class="btn btn-sm btn-success" href="emp" th:href="@{/emp}">员工添加</a>

    emp get 请求到员工添加页面

    emp post 添加员工

  

  其中部门为后台查出来的,前后台处理

<select class="form-control">
<option th:value="${dept.id}" th:each="dept:${depts}" th:text="dept.departmentName"></option>
</select>

  点击添加按钮 post 到 emp为添加功能

<form ah:action="@{/emp}" method="post">

  员工添加controller

  修改日期格式:spring.mvc.date-format=yyyy-MM-dd

  员工修改:emp/id ------->get 方式

<a class="btn btn-sm btn-primary" th:href="@{/emp/} + ${emp.id}">编辑员工</a>

  页面需要回显:

    th:value="${emp!=null}?${emp.lastName}">

    th:checked="${emp!=null}?${emp.gender==1}" / gender==0

    th:selected="${emp!=null}?${dept.id==emp.department.id}"

  如何发送put请求,到员工修改controller

  删除:delete请求

  出现了按钮换行 因为 form的添加 所以进行修改

  设置按钮del_uri

    button 设置 :th:attr="del_uri=@{emp/} + ${emp.id}"

    form 设置:id="deleteEmpForm"

  最后效果:

spring boot 尚桂谷学习笔记05 ---Web的更多相关文章

  1. spring boot 尚桂谷学习笔记04 ---Web开始

    ------web开发------ 1.创建spring boot 应用 选中我们需要的模块 2.spring boot 已经默认将这些场景配置好了 @EnableAutoConfiguration ...

  2. spring boot 尚桂谷学习笔记10 数据访问02 mybatis

    数据访问 mybatis 创建一个 springboot 工程,模块选择 sql 中 mysql(数据驱动), jdbc(自动配置数据源), mybatis Web模块中选择 web pom 引入: ...

  3. spring boot 尚桂谷学习笔记11 数据访问03 JPA

    整合JPA SpringData 程序数据交互结构图 (springdata jpa 默认使用 hibernate 进行封装) 使用之后就关注于 SpringData 不用再花多经历关注具体各个交互框 ...

  4. spring boot 尚桂谷学习笔记09 数据访问

    springboot 与数据库访问 jdbc, mybatis, spring data jpa,  1.jdbc原生访问 新建项目 使用 springboot 快速构建工具 选中 web 组件 sq ...

  5. spring boot 尚桂谷学习笔记07 嵌入式容器 ---Web

    ------配置嵌入式servlet容器------ springboot 默认使用的是嵌入的Servlet(tomcat)容器 问题? 1)如何定制修改Servlet容器的相关配置: 1.修改和se ...

  6. spring boot 尚桂谷学习笔记08 Docker ---Web

    ------Docker------ 简介:Docker是一个开元的应用容器引擎,性能非常高 已经安装好的软件打包成一个镜像放到服务器中运行镜像 MySQL容器,Redis容器...... Docke ...

  7. spring boot 尚桂谷学习笔记06 异常处理 ---Web

    ------错误处理机制------ 默认效果 1 返回一个默认的错误页面 浏览器发送请求的请求头:优先接收 text/html 数据 客户端则默认响应json数据 : accept 没有说明返回什么 ...

  8. springboot 尚桂谷学习笔记03

    ------spring boot 与日志------ 日志框架: 市面上的日志框架: jul jcl jboss-logging logback log4j log4j2 ...... 左边一个门面 ...

  9. Spring实战第六章学习笔记————渲染Web视图

    Spring实战第六章学习笔记----渲染Web视图 理解视图解析 在之前所编写的控制器方法都没有直接产生浏览器所需的HTML.这些方法只是将一些数据传入到模型中然后再将模型传递给一个用来渲染的视图. ...

随机推荐

  1. [CF643E]Bear and Destroying Subtrees(期望,忽略误差)

    Description: ​ 给你一棵初始只有根为1的树 ​ 两种操作 ​ 1 x 表示加入一个新点以 x为父亲 ​ 2 x 表示以 x 为根的子树期望最深深度 ​ 每条边都有 \(\frac{1}{ ...

  2. let/const及块级作用域

    本系列是在平时阅读.学习.实际项目中有关于es6中的新特性.用发的简单总结,目的是记录以备日后温习:本系列预计包含let/const.箭头函数.解构.常用新增方法.Symbol.Set&Map ...

  3. Codeforces 1061C (DP+滚动数组)

    题面 传送门 分析 考虑DP 设\(dp[i][j]\)表示前i个数选出的序列长度为j的方案数 状态转移方程为: \[ dp[i][j]= \begin{cases}dp\left[ i-1\righ ...

  4. P4843 清理雪道(上下界网络流)

    P4843 清理雪道 上下界最小流 我们先搞一遍上下界可行流(转) 回忆上下界最大流的写法:在可行流的残量网络$s\ -\ t$上跑最大流,答案为可行流$+$残量网络的最大流 那么上下界最小流的写法呢 ...

  5. grep命令用关系或查询多个字符串

    bcmsh ps | grep -E 'port|ge2 ' bcmsh ps | grep 'port\|ge2 ' 我的目的是筛选出含有 ‘port’ 或者含有 ‘ge2 ’ 的行,上面的第一行参 ...

  6. NGUI动态字体的创建(font maker)

    1,打开font maker 2,在font maker中创建选择动态字体 PS: 1,动态字体相对静态字体来说,动态字体比较消耗性能 2,静态字体是创建在图集中,这也是没那么消耗性能的原因

  7. 20191107PHP创建数组练习

    数组练习 <?php //创建的方式 //1 $arr=array(20,30,50); $arr1=[30,60,70]; //3 //当遇到这种情况的时候键(key)是相同的,会取后面的赋值 ...

  8. ajax axios 下载文件时如何获取进度条 process

    最近项目需要做一个下载文件的进度条,看网上上传文件进度条下载,特分享出来方便大家查阅 <!DOCTYPE html> <html> <head>     <m ...

  9. eclipse 设置注释模板

    window->preference->java->code  styple->code template->Comments Types /** * @author $ ...

  10. YouCompleteMe报错可能是第三方库没有

    git submodule update --init --recursive 到YouCompleteMe安装目录下,执行上面的命令