JavaEE项目总结(1)

news2024/11/15 15:43:52

一、在vue项目中安装axios
 

由于需要使用axios框架进行异步请求,所以需要在vue项目中安装axios框架。在官方下载速度较慢,所以选择更换镜像源(我使用的是华为云镜像)

在项目终端中输入npm config set registry http://mirrors.cloud.tencent.com/npm/

更换后通过在终端输入npm config get registry检查当前镜像源

二、前端向后端发送请求 

用户在浏览器进行操作,而这些操作最开始到达的是前端。这时候需要前端向后端发出响应。

我们以一个vue项目的登录功能为例,当用户输入了账户密码并点击登录是,前端需要拿到账户密码的数据并向后端发送

<!-- 一个.vue文件是一个组件,可以理解为一个页面,但是和页面不同 
  内容都写在一个template标签中,
  template标签必须有一个根标签
-->
<template>
	 <div class="login_container">
	     <!-- 登录盒子-->
	     <div class="login_box">
	          <!-- 头像盒子-->
	          <div class="img_box">
	                <img src="./assets/logo.png" />
	          </div>
			  
			<!-- 表单 -->
			<div style="margin-top: 100px; padding-right: 50px;">
				
				<el-form ref="form" label-width="80px">
					<!-- 第一栏 -->
					<el-form-item label="账号">
						 <el-input v-model="account"></el-input>
					</el-form-item>
					<!-- 第二栏 -->
					<el-form-item label="密码" show-password>
						 <el-input v-model="password"></el-input>
					</el-form-item>
					<!-- 按钮 -->
					 <el-form-item>
						<el-button type="primary"  @click="save()">登录</el-button>
						<el-button>取消</el-button>
					  </el-form-item>
					  
				</el-form>  
			</div>
				
		
	     </div>
	  </div>
</template>

<script>
/* 导出组件,并为组件定义数据,函数,生命周期函数 */
 export default{
	 data(){
		 return{
			 account:'admin',
			 password:'111'
		 }
	 },
	 methods:{
		 save(){
			 if(this.account.length==0){
				 this.$message({
				           message: '账号不得为空',
				           type: 'warning'
				         });
						 return;
			 }
			 if(this.password.length==0){
				 this.$message({
				           message: '密码不得为空',
				           type: 'warning'
				         });
						 return;		
			 }
			 // 向后端交互"/login","account="+this.account+"&password="+this.password
			 this.$http.post("login","account="+this.account+"&password="+this.password).then((resp)=>{
			 				/* 后端响应的结果 */
			 				
			 })
			 	
		 }
	 }
 }
</script>

<style>
  .login_container{
    height: 100vh;
    margin: 0px;
    padding: 0px;
	background-image: url(assets/bg.png);
  }

    .login_box{
      width: 450px;
      height: 350px;
      background-color: #fff;
      border-radius: 10px;
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%,-50%);
	  opacity: 0.95;
    }

    .img_box{
       width: 130px;
       height: 130px;
       position: absolute;
       left: 50%;
       transform: translate(-50%,-50%);
       background-color: #fff;
       border-radius: 50%;
       padding: 5px;
       border: 1px solid #eee;
    }
    
    .img_box img{
         width: 100%;
         height: 100%;
         border-radius: 50%;
         background-color: #eee;
     }
</style>

三、后端请求的处理

        后端处理主要分成三个步骤,简单来说就是"接化发"。

        接是接收来自前端的请求,化是在后端进行处理,发是对前端进行响应。这三个步骤也是后端的基本作用

登录servlet

package com.wbc.dorm.web;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wbc.dorm.dao.LoginDao;
import com.wbc.dorm.model.Admin;
import com.wbc.dorm.model.Result;
import com.wbc.dorm.util.JWTUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/*登录处理servlet*/
@WebServlet(urlPatterns = "/login",name = "login", loadOnStartup = 1)
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*登录请求的账号密码*/
        String account = req.getParameter("account");
        String password = req.getParameter("password");
        //System.out.println(account);
        //System.out.println(password);
        Result result = null;
        PrintWriter printWriter = resp.getWriter();
        /*调用dao层查询账号密码是否正确*/

        try {
            LoginDao loginDao = new LoginDao();
            Admin admin = loginDao.login(account, password);
            //System.out.println(admin.toString());
            if (admin!=null){
                //将admin放入标准化响应模型
                result = new Result(200, "登陆成功", admin);
            }
            else {
                result = new Result(201, "账号或密码错误", null);

            }
        } catch (Exception e) {
            e.printStackTrace();
            result = new Result(500, "系统忙", null);
        }
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = objectMapper.writeValueAsString(result);
        printWriter.print(jsonString);
    }
}

管理员模型

package com.wbc.dorm.model;

public class Admin {
    private int id;
    private String account;
    private String password;
   
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "Admin{" +
                "id=" + id +
                ", account='" + account + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

与数据库交互的dao

package com.wbc.dorm.dao;

import com.wbc.dorm.model.Admin;
import com.wbc.dorm.model.Admin;

import java.sql.*;

public class LoginDao {
    public Admin login(String username, String password) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url ="jdbc:mysql://127.0.0.1:3306/dormdb?serverTimezone=Asia/Shanghai";//定义连接sql所需的url
        String users ="root";//用户名
        String passwords ="Wbc11280";//密码
        //建立连接
        Connection connection = DriverManager.getConnection(url,users,passwords);//建立连接
        //预编译
        PreparedStatement preparedStatement =connection.prepareStatement("select id,account from admin where account = ? and password = ?");
        try{
            //传入数据
            preparedStatement.setObject(1, username);
            preparedStatement.setObject(2, password);
            //查询操作
            ResultSet resultSet = preparedStatement.executeQuery();//将查询结构封装到ResultSet类型的对象中 需要将数据封装到指定类型的对象中
            Admin admin = null;
            while (resultSet.next()) {
                admin = new Admin();
                admin.setId(resultSet.getInt("id"));
                admin.setAccount(resultSet.getString("account"));
//                System.out.println(admin.toString());
            }
            return admin;
            //return null;
        }
        finally {
            if(preparedStatement != null){
                preparedStatement.close();
            }
            if(connection != null){
                connection.close();
            }
        }
    }
}

四、前端接收响应并做处理

当后端程序向前端响应后,前端需要接收响应并作出响应的处理

// 向后端交互"/login","account="+this.account+"&password="+this.password
			 this.$http.post("login","account="+this.account+"&password="+this.password).then((resp)=>{
			 				/* 后端响应的结果 */
			 				if(resp.data.code==200){
								sessionStorage.setItem("account",resp.data.data.account);//存储到绘画空间,浏览器内部存储
					
			 					this.$router.push("/main");
			 				}
			 				else if(resp.data.code==201){
			 					this.$message({message:resp.data.message,type:'warning'})
			 				}
			 				else if(resp.data.code==500){
			 					this.$message({message:resp.data.message,type:'warning'})
			 				}
			 })

根据后端传来的标准化响应模型对象中的状态码,来做出对用户的响应,如登陆成功跳转到主页面,登陆失败根据状态码给出相应提示

说明:

        sessionStorage.setItem(key, value)可以将浏览器中的数据存储到浏览器中的会话空间,只要窗口打开,数据就可以一直使用,直到界面关闭或者通过sessionStorage.clear()方法手动清楚。会话空间的数据可以通过sessionStorage.getItem(key)方法取出,从而在整个项目中共享数据。

五、路由导航守卫

当我们有了登录验证功能之后,肯定不希望用户通过路由导航(直接输入网址)的方式越过登录直接进入到主页面。如果在每次跳转之后都进行判断则相当的麻烦

<template>
	<div>
		<el-container>
		  <el-header style="text-align: right; font-size: 12px">
			  <div class="header-title">后台管理系统</div>
						<el-dropdown>
						  <i class="el-icon-setting" style="margin-right: 15px"></i>
						  <el-dropdown-menu slot="dropdown" >
							<el-dropdown-item>主页</el-dropdown-item>
							<el-dropdown-item>修改密码</el-dropdown-item>
							<el-dropdown-item><span @click="logout()">安全退出</span></el-dropdown-item>
						  </el-dropdown-menu>
						</el-dropdown>
						<span>{{account}}</span>
		    </el-header>
			
		  <el-container>
		     <el-aside width="200px" style="background-color: rgb(238, 241, 246)">
		        <el-menu :default-openeds="['1', '3']" router>
		          <el-submenu index="1">
					  <template slot="title"><i class="el-icon-message"></i>操作菜单</template>
		            <el-menu-item-group>
		              <el-menu-item index="/majorlist">专业管理</el-menu-item>
		              <el-menu-item index="/studentlist">学生管理</el-menu-item>
					  <el-menu-item index="1-3">学院管理</el-menu-item>
		            </el-menu-item-group>
		          </el-submenu>
		        </el-menu>
		      </el-aside>
		    <el-main>
				<router-view></router-view>
			</el-main>
		  </el-container>
		  
		</el-container>
	</div>
</template>

<script>
	export default{
		
		data(){
			return{
				account:"",
				
			}
		},
		methods:{
			logout(){
				this.$confirm('您确定要退出么?', '提示', {
				          confirmButtonText: '确定',
				          cancelButtonText: '取消',
				          type: 'warning'
				        }).then(() => {
				          this.$message({
				            type: 'success',
				            message: '退出成功成功!'
				          });
						  sessionStorage.clear();
						  this.$router.push("/login")
				        })
			}
		},
		mounted(){
			this.account=window.sessionStorage.getItem("account");//将account存入路由器内部
			console.log(this.account);
			if(account==null){
				 this.$router.push("/login")
			}
		}
	}
</script>

<style>
  .el-header {
    background-color: #00a7fa;
    color: #333;
    line-height: 60px;
  }

  .header-title{
     width: 300px;
     float: left;
     text-align: left;
     font-size: 20px;
     color: white;
  }
  
  .el-main{
	  background-color: aliceblue;
	  height: 100vh;
  }
</style>

需要在每一次跳转中都进行一次判断。

而我们所使用的axios框架为我们提出了更加方便的解决方法------路由导航守卫。我们可以通过在路由中配置路由导航守卫,在每一次跳转时自动执行代码,进行判断是否已经登录

在/router/index.js文件中定义路由组件代码下方加入如下代码

//配置路由导航守卫
//每当进行一次组件路由时,就会触发导航守卫
rout.beforeEach((to,from,next)=>{
	if(to.path=='/login'){//如果用户访问的登录页,直接放行
		return next();//继续访问
	}	
	else{
	var account = window.sessionStorage.getItem("account");//获取路由器中存储的管理员信息
	if(account==null){//如果为空说明没有登录
		return next("/login");//跳转到登陆页面
	}
	else{//已经登陆
		next();//继续访问
	}
 }
})

如此我们就快要省去每次跳转判断的代码

<template>
	<div>
		<el-container>
		  <el-header style="text-align: right; font-size: 12px">
			  <div class="header-title">后台管理系统</div>
						<el-dropdown>
						  <i class="el-icon-setting" style="margin-right: 15px"></i>
						  <el-dropdown-menu slot="dropdown" >
							<el-dropdown-item>主页</el-dropdown-item>
							<el-dropdown-item>修改密码</el-dropdown-item>
							<el-dropdown-item><span @click="logout()">安全退出</span></el-dropdown-item>
						  </el-dropdown-menu>
						</el-dropdown>
						<span>{{account}}</span>
		    </el-header>
			
		  <el-container>
		     <el-aside width="200px" style="background-color: rgb(238, 241, 246)">
		        <el-menu :default-openeds="['1', '3']" router>
		          <el-submenu index="1">
					  <template slot="title"><i class="el-icon-message"></i>操作菜单</template>
		            <el-menu-item-group>
		              <el-menu-item index="/majorlist">专业管理</el-menu-item>
		              <el-menu-item index="/studentlist">学生管理</el-menu-item>
					  <el-menu-item index="1-3">学院管理</el-menu-item>
		            </el-menu-item-group>
		          </el-submenu>
		        </el-menu>
		      </el-aside>
		    <el-main>
				<router-view></router-view>
			</el-main>
		  </el-container>
		  
		</el-container>
	</div>
</template>

<script>
	export default{
		
		data(){
			return{
				account:"",
				
			}
		},
		methods:{
			logout(){
				this.$confirm('您确定要退出么?', '提示', {
				          confirmButtonText: '确定',
				          cancelButtonText: '取消',
				          type: 'warning'
				        }).then(() => {
				          this.$message({
				            type: 'success',
				            message: '退出成功成功!'
				          });
						  sessionStorage.clear();
						  this.$router.push("/login")
				        })
			}
		},
		mounted(){
			this.account=window.sessionStorage.getItem("account");//将account存入路由器内部
			console.log(this.account);
			/* if(account==null){
				 this.$router.push("/login")
			} */
		}
	}
</script>

<style>
  .el-header {
    background-color: #00a7fa;
    color: #333;
    line-height: 60px;
  }

  .header-title{
     width: 300px;
     float: left;
     text-align: left;
     font-size: 20px;
     color: white;
  }
  
  .el-main{
	  background-color: aliceblue;
	  height: 100vh;
  }
</style>

六、web前后端之间的会话跟踪

        当我们在登陆成功后需要进行其他操作时,前端会像后端发送http请求。但http请求是无状态的,因此后端不知道是谁在进行操作。对会话进行跟踪 就是为了解决这样的问题。

        会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话过程。 给客户端们颁发一个通行证,每人一个,无论谁访问都必须携带自己通行证。 这样服务器就能从通行证上确认客户身份了。

我们大致可以将会话跟踪描述为下图的过程

当我们在

具体实现

(1)在登陆成功后,在后端为用户生成一个token字符串

token令牌,可以理解为身份证号,是该用户唯一标识字符串,通过这个字符串进行前后端验证。

我们可以通过jwt组件为管理员生成token令牌

说明:

token令牌分为三部分:声明、载荷、签证

声明包含着生成类型和加密算法的基本信息,载荷包含着用户信息。二者通过base64转码生成,此过程可逆,不包含加密,因此不建议在载荷中加入用户关键信息。

签证结合前两部分以及密钥,加密生成,故密钥十分重要

我们通过maven添加依赖

<dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.8.2</version>
        </dependency>

并在服务器中注册(web.xml) 

 <!--验证token过滤器-->
    <filter>
        <filter-name>tokenfilter</filter-name>
        <filter-class>com.wbc.dorm.filter.AdminTokenFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>tokenfilter</filter-name>
        <!--请求地址中有api地址的Servlet进入过滤器-->
        <url-pattern>/api/*</url-pattern>
    </filter-mapping>

由于登录界面不需要生成token,所以通过在其他配置信息的地址前添加/api来区分

将jwt的util稍作修改直接拿来用

package com.wbc.dorm.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.wbc.dorm.model.Admin;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT工具类
 */
public class JWTUtil {

    /**
     * 根据用户id,账号生成token
     * @param admin
     * @return
     */
    public static String getToken(Admin admin) {
        String token = "";
        try {
            //过期时间 为1970.1.1 0:0:0 至 过期时间  当前的毫秒值 + 有效时间
            Date expireDate = new Date(new Date().getTime() + 10000*1000);
            //秘钥及加密算法
            Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
            //设置头部信息
            Map<String,Object> header = new HashMap<>();
            header.put("typ","JWT");
            header.put("alg","HS256");
            //携带id,账号信息,生成签名
            token = JWT.create()
                    .withHeader(header)//设置头部
                    .withClaim("id",admin.getId())//设置载荷
                    .withClaim("account",admin.getAccount())//设置载荷
                    .withExpiresAt(expireDate)//设置token有效时间
                    .sign(algorithm);//设置密钥
        }catch (Exception e){
            e.printStackTrace();
            return  null;
        }
        return token;
    }

    /**
     * 验证token是否有效
     * @param token
     * @return
     */
    public static boolean verify(String token){
        try {
            //验签
            Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (Exception e) {//当传过来的token如果有问题,抛出异常
            return false;
        }
    }

    /**
     * 获得token 中playload部分数据,按需使用
     * @param token
     * @return
     */
    public static DecodedJWT getTokenInfo(String token){
        return JWT.require(Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE")).build().verify(token);
    }

}

添加Admin内的成员变量adminToken,并增加相应的get、set方法。

package com.wbc.dorm.model;

public class Admin {
    private int id;
    private String account;
    private String password;
    private String adminToken;

    public String getAdminToken() {
        return adminToken;
    }

    public void setAdminToken(String adminToken) {
        this.adminToken = adminToken;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "Admin{" +
                "id=" + id +
                ", account='" + account + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

并在登录servlet中添加相应代码以生成token

package com.wbc.dorm.web;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wbc.dorm.dao.LoginDao;
import com.wbc.dorm.model.Admin;
import com.wbc.dorm.model.Result;
import com.wbc.dorm.util.JWTUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/*登录处理servlet*/
@WebServlet(urlPatterns = "/login",name = "login", loadOnStartup = 1)
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*登录请求的账号密码*/
        String account = req.getParameter("account");
        String password = req.getParameter("password");
        //System.out.println(account);
        //System.out.println(password);
        Result result = null;
        PrintWriter printWriter = resp.getWriter();
        /*调用dao层查询账号密码是否正确*/

        try {
            LoginDao loginDao = new LoginDao();
            Admin admin = loginDao.login(account, password);
            //System.out.println(admin.toString());
            if (admin!=null){

                //登陆成功后,为admin生成一个token字符串
                //使用jwt组件为管理员生成公私密钥
                String adminToken = JWTUtil.getToken(admin);
                //将adminToken放入admin
                admin.setAdminToken(adminToken);
                //将admin放入标准化响应模型
                result = new Result(200, "登陆成功", admin);
            }
            else {
                result = new Result(201, "账号或密码错误", null);

            }
        } catch (Exception e) {
            e.printStackTrace();
            result = new Result(500, "系统忙", null);
        }
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = objectMapper.writeValueAsString(result);
        printWriter.print(jsonString);
    }
}

(2)在浏览器中存储token,每次发送请求时将身份码一同发出

在登录时,接收后端相应处,添加接收身份码的代码,并将其添加到会话空间

sessionStorage.setItem("adminToken",resp.data.data.adminToken);

在我们操作发送请求时,如果在发送请求时,通过字符串拼接将身份码一同发于后端,实在过于麻烦,幸好axios为我们提供了请求拦截的功能

在main.js中添加如下代码,可以将身份码添加到请求头中,直接发送

//axios 请求拦截
axios.interceptors.request.use(config =>{
	 //为请求头对象,添加Token验证的token字段
	config.headers.adminToken = window.sessionStorage.getItem('adminToken');
	 return config;
 });

 (3)在后端创建一个过滤器,用于检测token的正确性,正确则退出过滤器继续响应,错误则直接向前端响应并给出状态码和提示信息

package com.wbc.dorm.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wbc.dorm.model.Result;
import com.wbc.dorm.util.JWTUtil;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;

public class AdminTokenFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //父类向子类转换(强制类型转换)
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String adminToken = request.getHeader("adminToken");
        //验证token
        Boolean res= JWTUtil.verify(adminToken);
        System.out.println(res);
        //处理验证结果
        if(res){
            filterChain.doFilter(request, servletResponse);//离开过滤器继续向下执行
        }
        else{
            //向前端进行响应
            Result result = new Result(401,"token验证失败,请重新登录",null);
            PrintWriter printWriter = new PrintWriter(servletResponse.getWriter());
            printWriter.write(new ObjectMapper().writeValueAsString(result));
        }


    }
}

在前端中main.js中添加响应拦截器(类似于javaEE中的过滤器),用于拦截后端的身份码错误响应

 // 添加响应拦截器
axios.interceptors.response.use((resp) =>{
	//正常响应拦截
	if(resp.data.code==500){
		ElementUI.Message({message:resp.data.message,type:"error"});
		return;
	 }
	 if(resp.data.code==401){
		 ElementUI.Message({message:resp.data.message,type:"error"});
		 sessionStorage.clear();
		router.replace("/login");
	 }
	 return resp;
 });

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

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

相关文章

MES系统:制造业转型升级的驱动力与效益源泉

制造业之所以需要并采纳MES系统&#xff08;Manufacturing Execution System&#xff0c;制造执行系统&#xff09;&#xff0c;主要是出于以下几个方面的考虑和需求。MES系统能够为企业带来显著的好处&#xff0c;具体体现在以下几个方面&#xff1a; 制造业需要MES系统的原因…

信贷风控架构一张图

记得刚入门风控时,由于做的模型岗,总有一种不能窥探风控全貌的疑惑。随着经验的积累,以及一些岗位的体验,慢慢对风控有了更清晰的认知。本文以一张图的形式简单地呈现信贷风控架构,让你能快速窥探信贷风控全貌。 文章目录 一、什么是风险管控?二、信贷风控架构一张图三、…

PCDN日常应用--公共资源利用

1、前言 PCDN 是通过在 CDN 的边缘节点上部署代理服务器&#xff0c;来实现主动调度和传输内容的方法。当用户请求内容时&#xff0c;PCDN 将根据各个节点的负载情况、距离、传输速度等一系列因素来动态选择最优的节点来提供内容。这样的调度方式使得 PCDN 在面对大规模请求时能…

健康管理系统解决方案

产品简介 脉购CRM健康管理系统是一款集会员健康管理以及会员数字化营销于一体的系统解决方案&#xff0c;旨在帮助企业更好地提供个性化的健康服务&#xff0c;维护好会员关系&#xff0c;通过有效的营销手段增加健康会员粘性和满意度&#xff0c;最终达到业绩增长的目的。 核…

云计算第三阶段---DBA Day2 -- Day4

DBA DAY2 一、常用函数、 常用函数 按使用方式分类按用途分类 ○单行函数 ○分组函数 ○字符函数 ○数学函数 ○日期函数 字符函数实例&#xff1a; ●LENGTH(str)&#xff1a;返字符串长度&#xff0c;以字节为单位 mysql> select length(abc); --------------- | l…

【NXP-MCXA153】TFT驱动移植

介绍 GC9A01是一款1.28寸的圆形TFT显示屏模块&#xff0c;分辨率为240x240&#xff0c;支持三种颜色格式&#xff1a;RGB444、RGB565、RGB666&#xff0c;本次实验将在NXP-MCXA153开发板上移植TFT LCD驱动 移植流程 ① 绑定TFT LCD上面的GPIO&#xff0c;如SCL_PIN、SDA_PIN…

Java - File、IO流

File类 File是java.io.包下的类&#xff0c;File类的对象&#xff0c;用于代表当前操作系统的文件&#xff08;可以是文件、文件夹&#xff09; File类只能对文件本身进行操作&#xff0c;不能读写文件里面存储的数据。 创建File类的对象&#xff1a; //创建file对象//1.具体…

House of Roman / malloc_printerr间接调用malloc函数执行malloc_hook

文章目录 House of Roman介绍&#xff1a;原理&#xff1a;例子&#xff1a;思路&#xff1a;分析&#xff1a;利用&#xff1a; House of Roman 介绍&#xff1a; House of Roman 这个技巧说简单点其实就是 fastbin attack 和 Unsortbin attack 结合的一个小 trick。该技术用…

python-字符串操作(赛氪OJ)

[题目描述] 给定长度为 n 的只有小写字母的字符串 s &#xff0c;进行 m 次操作&#xff0c;每次将 [l,r] 范围内所有 c1 字符改成 c2 &#xff0c;输出操作完的字符串。输入格式&#xff1a; 第一行两个数 n , m &#xff0c; 第二行一个字符串 s &#xff0c; 之后 m 行&…

Ubuntu修改命令提示符格式PS1

命令提示符组成 通过Xshell进入Ubuntu的默认提示符是这样的 rootDESKTOP:~# root: 当前登录用户DESKTOP&#xff1a;主机名~: 当前目录名&#xff08;即用户主目录&#xff09;#&#xff1a;超级用户权限(root用户显示)$: 普通用户权限(非root用户显示) 修改命令提示符 step1…

linux 环境下 配置jenkins前端服务

前期准备 如果没有&#xff0c;需要安装插件 <b>HH:mm:ss</b> <b>HH:mm:ss.S</b> $PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS! 连接服务器的密码 测试 前端部署 需要安装nodejs的插件 执行脚本 node -v npm install rm -rf ./dist…

未解决:不同类型的数据用memcpy然后打印(printf)出问题

引子&#xff1a; 本来是搜memcpy在拷贝两个数组时两数组下标类型不同的问题&#xff0c;即&#xff0c;若一个数组是很长&#xff0c;其下标用long型&#xff0c;要将此数组的一小段拷贝到另一个数组中&#xff0c;这另一个数组的下标只需要用int型&#xff0c;不确定会不会出…

C++高性能编程:ZeroMQ vs Fast-DDS发布-订阅模式下性能对比与分析

文章目录 0. 引言1. 目标&#xff1a;ZeroMQ与Fast-DDS性能对比2. ZeroMQ vs Fast-DDS - 延迟基准测试2.1 一对一发布-订阅延迟2.2 一对多发布-订阅延迟 3. ZeroMQ vs Fast-DDS - 吞吐量基准测试4. 方法论5. 结论6. 参考 0. 引言 高要求的分布式系统催生了对轻量级且高性能中间…

MATLAB口罩检测系统

一、应用背景 作为数字图像处理和计算机视觉领域的一个重要组成部分&#xff0c;利用摄像机对图像进行采集&#xff0c;从图像中检测人脸并进行口罩穿戴的识别的有着非常重要的研究意义和应用价值。面对突如其来的新型肺炎疫情&#xff0c;人们生活秩序被严重打乱。跟普通流感…

前端Vue监听路由变化, 点击页面内按钮跳转菜单更改导航菜单选中状态

1.问题描述 当我们进入页面时的菜单导航栏是默认选中的状态如图 点击博客园效果如图 问题1&#xff1a; 但是当我们点击页面上方返回按钮时&#xff0c;导航栏选中状态没有改变 分析问题1&#xff1a; 这个问题是因为页面改变后页面里面存储的菜单导航栏的is-active属性没有改…

WIFI 密码

要破解 WIFI 密码&#xff0c;首先要抓到 WIFI 的握手包&#xff0c;要想得到 WIFI 的握手包&#xff0c;就需要在监听时刚好有设备连接了该 WIFI&#xff0c;但这就需要运气加成&#xff0c;因此可以我们可以主动将该 WIFI 的设备踢下去&#xff0c;一般设备就会自动连接该 WI…

机器学习:逻辑回归算法实现鸢尾花预测和银行数据处理

1、鸢尾花预测 1、特征选择 2、对特征处理 trainpd.read_excel("鸢尾花训练数据.xlsx") testpd.read_excel("鸢尾花测试数据.xlsx") x_traintrain[["萼片长(cm)","萼片宽(cm)","花瓣长(cm)","花瓣宽(cm)"]] y_tr…

HTML及CSS面试题4

1、BFC 1.1、介绍BFC及其应用 补充——触发BFC的方式&#xff0c;常见的有&#xff1a; 设置浮动overflow设置为&#xff1a;auto、scroll、hiddenpositon设置为&#xff1a;absolute、fixed 介绍&#xff1a; ○ 所谓BFC&#xff0c;指的是&#xff1a;一个独立的布局环境&am…

C2M商业模式分析与运营平台建设解决方案(一)

C2M&#xff08;Customer to Manufacturer&#xff09;商业模式通过直接将消费者需求与生产商对接&#xff0c;极大提升了生产效率和市场响应速度&#xff0c;本文将探讨如何通过构建高效的运营平台&#xff0c;利用大数据分析、人工智能算法及灵活的供应链管理&#xff0c;优化…

四川汇昌联信做拼多多电商怎么样?

近年来&#xff0c;拼多多凭借其独特的社交电商模式迅速崛起&#xff0c;成为国内领先的电商平台之一。四川汇昌联信作为一家专注于电商领域的企业&#xff0c;涉足拼多多平台无疑是顺应市场趋势的明智之举。那么&#xff0c;四川汇昌联信在拼多多平台上的表现如何呢? 一、产品…