Vue + Spring Boot 项目实战(七):前端路由与登录拦截器

文章目录

    • 前言
  • 一、前端路由
  • 二、使用 History 模式
  • 三、后端登录拦截器
    • 3.1. LoginController
    • 3.2. LoginInterceptor
    • 3.3. WebConfigurer
    • 3.4. 效果检验
  • 四、Vuex 与前端登录拦截器
    • 4.1. 引入 Vuex
    • 4.2. 修改路由配置
    • 4.3. 使用钩子函数判断是否拦截
    • 4.4. 修改 Login.vue
    • 4.5. 效果检验

前言

这一篇主要讲前端路由与登录拦截器的实现。放在一起讲是因为我在开发登录拦截器时因为这个路由的问题遇到了很多坑,花费了很长时间,网上的解决方案都不怎么靠谱,综合了好几种办法才最终成功,其实关于这个部分能写两三篇文章,名字起好了还能多很多访问量,不过为了保证文章的质量我没有这么做,毕竟我不是大神,如果再不用点心,写出来的文章自己都不想再看第二遍,更别提能对大家有所帮助了。

一、前端路由

大家如果留心观察就会发现,之前我们做的页面的 URL 里有一个 # 号,这个 # 号有什么含义呢?

假设在 html 中有这么一段代码:<div id="test">This is a test</div>,如果我们想让页面定位到这个 div 所在的位置,可以加一个超链接 <a herf="#test">Jump to test</a>,这里的 # 被称为“锚点”,点击超链接,可以发现网页的 URL 发生了变化,但页面并不会跳转。

在互联网流量如此庞大的今天,我们需要想办法后端服务器的压力,利用 AJAX,我们可以不重载页面就刷新数据,如果再加上 # 号的特性(即改变 URL 却不请求后端),我们就可以在前端实现页面的整体变化,而不用每次都去请求后端。

为了实现前端路由,我们可以监听 # 号后面内容的变化(hashChange),从而动态改变页面内容。URL 的 # 号后面的地址被称为 hash ,估计是哪个大神拍脑袋想的,不用深究。这种实现方式我们称之为 Hash 模式,是非常典型的前端路由方式。

另一种常用的方式被称为 History 模式,这种方式使用了 History API,History API 顾名思义就是针对历史记录的 API ,这种模式的原理是先把页面的状态保存到一个对象(state)里,当页面的 URL 变化时找到对应的对象,从而还原这个页面。其实原本人家这个功能是为了方便浏览器前进后退的,不得不说程序员们的脑洞真大。使用了这种模式,就可以摆脱 # 号实现前端路由。

Vue 已经为我们提供了两种模式的前端路由,无需我们自己去实现。

二、使用 History 模式

首先我们把 Vue 中配置的路由从默认的 hash 模式切换为 histroy 模式。打开我们的前端项目 wj-vue,修改 router\index.js,加入 mode: 'history 这句话。整体代码如下:

import Vue from 'vue'
import Router from 'vue-router'
// 导入刚才编写的组件
import AppIndex from '@/components/home/AppIndex'
import Login from '@/components/Login'Vue.use(Router)export default new Router({mode: 'history',routes: [// 下面是固定写法{path: '/login',name: 'Login',component: Login},{path: '/index',name: 'AppIndex',component: AppIndex}]
})

运行项目,访问不加 # 号的 http://localhost:8080/login ,成功加载页面。
运行项目:npm run dev
在这里插入图片描述
浏览器访问:http://localhost:8080/login
在这里插入图片描述

接下来,我们把前端打包后部署在后端。这不是前后端分离项目推荐的做法,之前我们讲过其实应该把前后端分别部署在不同的服务器中,但实际上仍有不少项目会选择把前后端整合在一起,只使用一个服务器,所以这里我们也提及一下这种方式,但在之后的开发中不会这样部署。

先在项目目录执行 npm run build,控制台输出如下内容表明执行完毕:

在这里插入图片描述
在这里插入图片描述
这时在项目的 dist 文件夹下生成了 static 文件夹和 index.html 文件,把这两个文件,拷贝到我们后端项目的 wj\src\main\resources\static 文件夹下,一定要注意这个位置,这时后端配置的静态文件的 path,虽然看起来很诡异,但一般都不作修改。
在这里插入图片描述
接下来,打开后端项目并运行,访问 http://localhost:8443/index.html ,(注意输入后缀 .html)发现页面是空白的,但确实取到了这个页面。
在这里插入图片描述
再访问 http://localhost:8443/login ,发现跳转到了错误页面(White Error Page)
在这里插入图片描述
这里我们回顾一下单页面应用的概念,在我们这个项目中,其实只有 index.html 这一个页面,所有的其它内容都是在这个页面里动态渲染的。当我们直接在后端访问 /login 路径时,服务器会后端并没有这个路径对应的内容,所以返回了 Error Page。

为了获取到我们需要的内容,我们要想办法触发前端路由,即在后端添加处理内容,把 通过这个 URL 渲染出的 index.html 返回到浏览器。

在后端项目中新建一个 package 名为 error,新建实现 ErrorPageRegistrar 接口的类 ErrorConfig,把默认的错误页面设置为 /index.html,代码如下

package com.gblfy.wj.error;import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;@Component
public class ErrorConfig implements ErrorPageRegistrar {@Overridepublic void registerErrorPages(ErrorPageRegistry registry) {ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/index.html");registry.addErrorPages(error404Page);}}

重新启动项目,访问 http://localhost:8443/login ,成功进入登录页面。

在这里插入图片描述

三、后端登录拦截器

为了完善登录功能,我们需要限制未登录状态下对核心功能页面的访问。登录拦截可以由多种方式来实现,我们首先讲解后端拦截器的开发。(注意如果没有把前后端项目整合起来,就没有办法使用这种方式)

一个简单拦截器的逻辑如下:

1.用户访问 URL,检测是否为登录页面,如果是登录页面则不拦截
2.如果用户访问的不是登录页面,检测用户是否已登录,如果未登录则跳转到登录页面

3.1. LoginController

首先我们修改 LoginController 的内容。之前我们实现了通过查询数据库验证用户名是否正确,但仅此而已。

为了保存登录状态,我们可以把用户信息存在 Session 对象中(当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量不会丢失),这样在访问别的页面时,可以通过判断是否存在用户变量来判断用户是否登录。这是一种比较简单的方式,感兴趣的同学可以尝试别的方法。

修改后的代码内容如下:

package com.gblfy.wj.controller;import com.gblfy.wj.pojo.User;
import com.gblfy.wj.result.Result;
import com.gblfy.wj.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.HtmlUtils;import javax.servlet.http.HttpSession;@Controller
public class LoginController {@AutowiredUserService userService;@CrossOrigin@PostMapping(value = "/api/login")@ResponseBodypublic Result login(@RequestBody User requestUser, HttpSession session) {String username = requestUser.getUsername();username = HtmlUtils.htmlEscape(username);User user = userService.get(username, requestUser.getPassword());if (null == user) {return new Result(400);} else {session.setAttribute("user", user);return new Result(200);}}
}

其实只是添加了一条语句 session.setAttribute(“user”, user);

3.2. LoginInterceptor

新建 package 名为 interceptor,新建类 LoginInterceptor

Interceptor 即拦截器,在 Springboot 我们可以直接继承拦截器的接口,然后实现 preHandle 方法。preHandle 方法里的代码会在访问需要拦截的页面时执行。
代码如下:

package com.gblfy.wj.interceptor;import com.gblfy.wj.pojo.User;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {HttpSession session = httpServletRequest.getSession();String contextPath = session.getServletContext().getContextPath();String[] requireAuthPages = new String[]{"index",};String uri = httpServletRequest.getRequestURI();uri = StringUtils.remove(uri, contextPath + "/");String page = uri;if (begingWith(page, requireAuthPages)) {User user = (User) session.getAttribute("user");if (user == null) {httpServletResponse.sendRedirect("login");return false;}}return true;}private boolean begingWith(String page, String[] requiredAuthPages) {boolean result = false;for (String requiredAuthPage : requiredAuthPages) {if (StringUtils.startsWith(page, requiredAuthPage)) {result = true;break;}}return result;}
}

看起来似乎比较长,其实就是判断 session 中是否存在 user 属性,如果存在就放行,如果不存在就跳转到 login 页面。这里使用了一个路径列表(requireAuthPages),可以在里面写下需要拦截的路径。当然我们也可以拦截所有路径,那样就不用写这么多了,但会有逻辑上的问题,就是你访问了 \login 页面,仍然会需要跳转,这样就会引发多次重定向问题。

3.3. WebConfigurer

我们写完了拦截器,但是它却并不会生效,因为我们还没有把它配置到项目中。

新建 package 名为 config,新建类 MyWebConfigurer,代码如下:

package com.gblfy.wj.config;import com.gblfy.wj.interceptor.LoginInterceptor;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.*;@SpringBootConfiguration
public class MyWebConfigurer implements WebMvcConfigurer {@Beanpublic LoginInterceptor getLoginIntercepter() {return new LoginInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(getLoginIntercepter()).addPathPatterns("/**").excludePathPatterns("/index.html");}
}

通过这个配置类,我们添加了之前写好的拦截器。这里有一句非常重要的语句,即

registry.addInterceptor(getLoginIntercepter()).addPathPatterns("/**").excludePathPatterns("/index.html");

这条语句的作用是对所有路径应用拦截器,除了 /index.html。

之前我们在拦截器 LoginInterceptor 中配置的路径,即 index,触发的时机是在拦截器生效之后。也就是说,我们访问一个 URL,会首先通过 Configurer 判断是否需要拦截,如果需要,才会触发拦截器 LoginInterceptor,根据我们自定义的规则进行再次判断。

/index/index.html 是不同的,也就是说 /index 会触发拦截器而 /index.html 不会,但根据拦截器 LoginInterceptor 中我们定义的判断条件,以 /index 开头的路径都会被转发,包括 index.html

因为我们做的是单页面应用,之前通过配置 ErrorPage,实际上访问所有路径都会重定向到 /index.html 。我们直接在浏览器地址栏输入 /index 会触发拦截器,经过拦截器重定向到 /login,然后 /login 再经过 Configurer 的判断,再次触发拦截器,由于不在需要拦截的路径中,所以被放行,页面则重新定向到了 /index.html,如果没有再 Configurer 中取消对 /index.html 的拦截,则会再次触发拦截器,再次重定向到 /login,引发如下错误。
在这里插入图片描述
上述过程比较绕,这是我开发时的失误,但我觉得恰好可以帮助大家理解拦截器与单页面应用,所以保留了下来。

3.4. 效果检验

运行后端项目,访问http://localhost:8443/index,发现页面自动跳转到了 http://localhost:8443/login,输入用户名和密码登录,跳转到 http://localhost:8443/index , 这时可以把浏览器标签关掉,再在一个新标签页输入 http://localhost:8443/index ,发现不会被拦截。
在这里插入图片描述
在这里插入图片描述

四、Vuex 与前端登录拦截器

前面我们使用了后端拦截器,但这种拦截器只有在将前后端项目整合在一起时才能生效,而前后端分离的项目实际上不推荐这么做,接下来我们尝试用前端实现相似的功能。

实现前端登录器,需要在前端判断用户的登录状态。我们可以像之前那样在组件的 data 中设置一个状态标志,但登录状态应该被视为一个全局属性,而不应该只写在某一组件中。所以我们需要引入一个新的工具——Vuex,它是专门为 Vue 开发的状态管理方案,我们可以把需要在各个组件中传递使用的变量、方法定义在这里。之前我一直没有使用它,所以在不同组件传值的问题上十分头疼,要写很多多余的代码来调用不同组件的值,所以推荐大家从一开始就去熟悉这种管理方式。

4.1. 引入 Vuex

在我们的项目文件夹中,运行 npm install vuex --save,之后,在 src 目录下新建一个文件夹 store,并在该目录下新建 index.js 文件,在该文件中引入 vue 和 vuex,代码如下:
安装前:
在这里插入图片描述
安装后:
在这里插入图片描述

import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)

之后,我们在 index.js 里设置我们需要的状态变量和方法。为了实现登录拦截器,我们需要一个记录用户信息的变量。为了方便日后的扩展(权限认证等),我们使用一个用户对象而不是仅仅使用一个布尔变量。同时,设置一个方法,触发这个方法时可以为我们的用户对象赋值。完整的代码如下:

import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({state: {user: {username: window.localStorage.getItem('user' || '[]') == null ? '' : JSON.parse(window.localStorage.getItem('user' || '[]')).username}},mutations: {login (state, user) {state.user = userwindow.localStorage.setItem('user', JSON.stringify(user))}}
})

这里我们还用到了 localStorage,即本地存储,在项目打开的时候会判断本地存储中是否有 user 这个对象存在,如果存在就取出来并获得 username 的值,否则则把 username 设置为空。这样我们只要不清除缓存,登录的状态就会一直保存。

4.2. 修改路由配置

为了区分页面是否需要拦截,我们需要修改一下 src\router\index.js,在需要拦截的路由中加一条元数据,设置一个 requireAuth 字段如下:

    {path: '/index',name: 'AppIndex',component: AppIndex,meta: {requireAuth: true}}

完整的 index.js 代码如下:

import Vue from 'vue'
import Router from 'vue-router'
import AppIndex from '@/components/home/AppIndex'
import Login from '@/components/Login'Vue.use(Router)export default new Router({mode: 'history',routes: [{path: '/login',name: 'Login',component: Login},{path: '/index',name: 'AppIndex',component: AppIndex,meta: {requireAuth: true}}]`在这里插入代码片`
})

4.3. 使用钩子函数判断是否拦截

钩子函数及在某些时机会被调用的函数。这里我们使用 router.beforeEach(),意思是在访问每一个路由前调用。

打开 src\main.js ,首先添加对 store 的引用

import store from './store'

并修改 Vue 对象里的内容

new Vue({el: '#app',render: h => h(App),router,// 注意这里store,components: { App },template: '<App/>'
})

接着写 beforeEach() 函数

router.beforeEach((to, from, next) => {if (to.meta.requireAuth) {if (store.state.user.username) {next()} else {next({path: 'login',query: {redirect: to.fullPath}})}} else {next()}}
)

这个的逻辑很简单,首先判断访问的路径是否需要登录,如果需要,判断 store 里有没有存储 user 的信息,如果存在,则放行,否则跳转到登录页面,并存储访问的页面路径(以便在登录后跳转到访问页)。

完整的 main.js 代码如下:

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'// 引入ElementUI
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'var axios = require('axios')
// 设置反向代理,前端请求默认发送到 http://localhost:8443/api
axios.defaults.baseURL = 'http://localhost:8443/api'
// 全局注册,之后可在其它组件中通过 this.$axios 发送数据
Vue.prototype.$axios = axios
Vue.config.productionTip = false
// Vue使用ElementUI
Vue.use(ElementUI)router.beforeEach((to, from, next) => {if (to.meta.requireAuth) {if (store.state.user.username) {next()} else {next({path: 'login',query: {redirect: to.fullPath}})}} else {next()}
}
)/* eslint-disable no-new */
new Vue({el: '#app',render: h => h(App),router,// 注意这里store,components: { App },template: '<App/>'
})

4.4. 修改 Login.vue

之前的登录组件中,我们只是判断后端返回的状态码,如果是 200,就重定向到首页。在经过前面的配置后,我们需要修改一下登录逻辑,以最终实现登录拦截。

修改后的逻辑如下:

1.点击登录按钮,向后端发送数据
2.受到后端返回的成功代码时,触发 store 中的 login() 方法,把 loginForm 对象传递给 store 中的 user 对象
(*这里只是简单的实现,在后端我们可以通过用户名和密码查询数据库,获得 user 表的完整信息,比如用户昵称、用户级别等,返回前端,并传递给 user 对象,以实现更复杂的功能)
3.获取登录前页面的路径并跳转,如果该路径不存在,则跳转到首页

修改后的 login() 方法如下:

login () {var _this = thisconsole.log(this.$store.state)this.$axios.post('/login', {username: this.loginForm.username,password: this.loginForm.password}).then(successResponse => {if (successResponse.data.code === 200) {// var data = this.loginForm_this.$store.commit('login', _this.loginForm)var path = this.$route.query.redirectthis.$router.replace({path: path === '/' || path === undefined ? '/index' : path})}}).catch(failResponse => {})
}

完整的 Login.vue 代码如下

<template><body id="poster"><el-form class="login-container" label-position="left"label-width="0px"><h3 class="login_title">系统登录</h3><el-form-item><el-input type="text" v-model="loginForm.username"auto-complete="off" placeholder="账号"></el-input></el-form-item><el-form-item><el-input type="password" v-model="loginForm.password"auto-complete="off" placeholder="密码"></el-input></el-form-item><el-form-item style="width: 100%"><el-button type="primary" style="width: 100%;background: #505458;border: none" v-on:click="login">登录</el-button></el-form-item></el-form></body>
</template><script>export default {name: 'Login',data () {return {loginForm: {username: 'admin',password: '123'},responseResult: []}},methods: {login () {var _this = thisconsole.log(this.$store.state)this.$axios.post('/login', {username: this.loginForm.username,password: this.loginForm.password}).then(successResponse => {if (successResponse.data.code === 200) {// var data = this.loginForm_this.$store.commit('login', _this.loginForm)var path = this.$route.query.redirectthis.$router.replace({path: path === '/' || path === undefined ? '/index' : path})}}).catch(failResponse => {})}}}
</script><style>#poster {background:url("../assets/eva.jpg") no-repeat;background-position: center;height: 100%;width: 100%;background-size: cover;position: fixed;}body{margin: 0px;}.login-container {border-radius: 15px;background-clip: padding-box;margin: 90px auto;width: 350px;padding: 35px 35px 15px 35px;background: #fff;border: 1px solid #eaeaea;box-shadow: 0 0 25px #cac6c6;}.login_title {margin: 0px auto 40px auto;text-align: center;color: #505458;}</style>

4.5. 效果检验

同时运行前后端项目,访问 http://localhost:8080/index ,发现页面直接跳转到了 http://localhost:8080/login?redirect=%2Findex
在这里插入图片描述

输入账号密码后登录,成功跳转到 http://localhost:8080/index ,之后再次访问则无需登录(除非清除缓存)。

读者大人们请原谅我没有及时更新,作为一个不知名博主,十分感谢大家的支持。我会坚持下去的,希望大家都能坚持做自己想做的事,一起变得更加牛批!

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

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

相关文章

高手如何实践HBase?不容错过的滴滴内部技巧

摘要&#xff1a; HBase和Phoenix的优势大家众所周知&#xff0c;想要落地实践却问题一堆&#xff1f;replication的随机发送、Connection的管理是否让你头痛不已&#xff1f;本次分享中&#xff0c;滴滴以典型的应用场景带大家深入探究HBase和Phoenix&#xff0c;并分享内核改…

JS 打印 data数据_数据表格 Data Table - 复杂内容的15个设计点

表格是桌面应用中常见的内容型组件&#xff0c;它包含大量的信息和丰富的交互形式&#xff0c;表格具有极高的空间利用率&#xff0c;结构化的展示保证了数据可读性。高效、清晰且易用是进行表格设计的原则性要求。本文将从表格的内容组织到交互作一次汇总&#xff0c;作为数据…

神龙X-Dragon,这技术“范儿”如何?| 问底中国IT技术演进

在CSDN总部会议室&#xff0c;阿晶首次见到了阿里云智能研究员、弹性计算技术负责人张献涛——这位不仅仅在阿里云智能内部&#xff0c;在业内也是响当当的虚拟化技术大牛。现在回想起来&#xff0c;当时聊了没两句&#xff0c;阿晶就问了这样一个问题&#xff0c;“阿里云这款…

干货 | 蚂蚁金服是如何实现经典服务化架构往 Service Mesh 方向的演进的?

摘要&#xff1a; 小蚂蚁说&#xff1a; 蚂蚁金服在服务化上面已经经过多年的沉淀&#xff0c;支撑了每年双十一的高峰峰值。Service Mesh 作为微服务的一个新方向&#xff0c;在最近两年成为领域的一个大热点&#xff0c;但是如何从经典服务化架构往 Service Mesh 的方向上演进…

Vue + Spring Boot 项目实战(八):导航栏与图书页面设计

文章目录前言一、导航栏的实现1.路由配置2.使用 NavMenu 组件二、图书管理页面2.1. LibraryIndex.vue2.SideMenu.vue3.Books.vue前言 之前讲过使用 Element 辅助前端页面的开发&#xff0c;但是只用到了比较少的内容&#xff0c;这一篇我们来做一下系统的核心页面——图书管理…

pmsm simulink foc 仿真_仿真软件教程

很多朋友都建议我做个视频的整理&#xff0c;方便没看过之前内容的朋友方便查找&#xff0c;我觉得这个确实很有必要。下面内容是关于仿真软件方面&#xff1a;仿真环境&#xff1a;Simlpis 8.0类型简介VMC和CMC的LLC控制器仿真对比 第一节图文电压模式和电流模式LLC控制器的简…

日志采集中的关键技术分析

摘要&#xff1a; 从日志投递的方式来看&#xff0c;日志采集又可以分为推模式和拉模式&#xff0c;本文主要分析的是推模式的日志采集。概述日志从最初面向人类演变到现在的面向机器发生了巨大的变化。最初的日志主要的消费者是软件工程师&#xff0c;他们通过读取日志来排查问…

限时早鸟票 | 2019 中国大数据技术大会(BDTC)超豪华盛宴抢先看!

2019 年12月5-7 日&#xff0c;由中国计算机学会主办&#xff0c;CCF 大数据专家委员会承办&#xff0c;CSDN、中科天玑数据科技股份有限公司协办的 2019 中国大数据技术大会&#xff0c;将于北京长城饭店隆重举行。届时&#xff0c;超过百位技术专家及行业领袖将齐聚于此&…

机器学习和数据科学领域必读的10本免费书籍

摘要&#xff1a; 暑期来了&#xff0c;别出去溜达了&#xff0c;看书学习一波&#xff5e;在这个暑假&#xff0c;有兴趣的可以阅读一下这些免费的有关机器学习和数据科学的书籍&#xff0c;他们能给你打开一扇看清机器学习和数据科学的窗。如果在阅读完这一文章后想知晓更多免…

microsoft账号登陆一直在加载_英雄联盟手游下载,附带拳头账号注册教程

欢迎关注【花卷来了】公众号。如果喜欢本期节目请点赞、再看、分享给朋友吧~软件资源请回复文章底部今日关键词获取/排版&#xff1a;萌萌哒花卷/来源&#xff1a;采集自网络今日主题&#xff1a;最新英雄联盟手游下载&#xff0c;附带拳头账号注册教程英雄联盟手游今天正式公测…

机器学习者都应该知道的五种损失函数!

摘要&#xff1a; 还不知道这五种损失函数&#xff1f;你怎么在机器学习这个圈子里面混&#xff1f;在机器学习中&#xff0c;所有的机器学习算法都或多或少的依赖于对目标函数最大化或者最小化的过程&#xff0c;我们常常把最小化的函数称为损失函数&#xff0c;它主要用于衡量…

linux服务器监控zabbix,Linux监控之--使用ZABBIX监控web服务器

使用ZABBIX监控web服务器实验拓扑图&#xff1a;实验思路&#xff1a;nginx添加状态统计模块&#xff0c;编写nginx对应的状态统计脚本。zabbix-server导入nginx模板&#xff0c;并对主机实现监控。实验环境角色IP地址操作系统版本软件包Zabbix_server192.168.0.158/24Centos6.…

Facebook 约十亿美元收购脑机技术公司,助攻AR研发;苹果宣布新款 Mac Pro 在美国生产;谷歌称已实现量子霸权…...

关注并标星星CSDN云计算极客头条&#xff1a;速递、最新、绝对有料。这里有企业新动、这里有业界要闻&#xff0c;打起十二分精神&#xff0c;紧跟fashion你可以的&#xff01;每周三次&#xff0c;打卡即read更快、更全了解泛云圈精彩newsgo go go 小米MIX Alpha手机官方概念图…

知道这些用于数据科学和机器学习的GitHub存储库和Reddit主题吗?

摘要&#xff1a; 5月最热门的GitHub存储库和顶级Reddit讨论&#xff0c;戳进来~GitHub和Reddit都是比较有趣的平台&#xff0c;在这里&#xff0c;我不仅学习了数据科学的一些最佳应用&#xff0c;而且还了解数据科学家们是如何编程的。一直以来&#xff0c;GitHub都是开发人员…

l2-008 最长对称子串 (25分)_小学数学关于时间认识(时、分、秒)的几点总结

本文将通过对照学习一个个知识点&#xff0c;延伸出各种知识点的常用题型。一、时、分、秒之间的换算&#xff1a;1时60分 1分60秒这类题型考的是时间单位之间的换算&#xff0c;一种是大单位换小单位&#xff0c;一种是小单位换大单位。在之前的一篇文章里有关于换算的计算方法…

如何在阿里云上构建一个合适的Kubernetes集群

摘要&#xff1a; 声明 本文主要介绍如何在阿里云上构建一个K8S集群的实践&#xff0c;只是作为参考&#xff0c;大家可以根据实际情况做出调整。 集群规划 在实际案例中发现&#xff0c;有不少同学使用了很多的小规格的ECS来构建K8S集群&#xff0c;这样其实即没有达到省钱的目…

360断网急救箱_万事不求人,教你自己动手修复网络断网

日常使用中&#xff0c;我们经常会遇到原来好好的网络忽然无法上网的问题。在排除宽带没有问题&#xff0c;硬件交换机、路由器、网线没有问题的情况下&#xff0c;我们可以充分利用第三方工具的修复功能。前几天&#xff0c;我就遇到一例电脑不能上网的问题&#xff0c;同一办…

linux 网络dma驱动,S3C2410的Linux下DMA驱动程序开发

网上介绍Linux下的一般驱动程序开发示例浩如烟海&#xff0c;或是因为简单&#xff0c;关于DMA驱动的介绍却寥寥无几&#xff1b;近期因工作需要&#xff0c;花了几日时间开发了某设备在S3C2410处理器Linux下DMA通信的驱动程序&#xff0c;有感于刚接手时无资料借鉴的茫然&…

Pivotal冯雷:以数字化为核心竞争力的时代 自主可控是企业的“必然选择”

戳蓝字“CSDN云计算”关注我们哦&#xff01;随着互联网的飞速发展&#xff0c;特别是近年来随着社交网络、物联网、云计算以及多种传感器的广泛应用&#xff0c;以数量庞大&#xff0c;种类众多&#xff0c;时效性强为特征的非结构化数据不断涌现&#xff0c;数据的重要性愈发…

druid去掉广告

定位问题 产生广告的JS文件在 druid-1.1.19.jar/support/http/resources/js/common.js。 查看源码可知是buildFooter方法进行植入&#xff0c;由init方法调用。 解决方案&#xff1a; 找到对应的依赖jar包&#xff0c;如druid-1.1.19.jar 找到support/http/resource/js/comm…