Spring Social微信登录

news2024/12/26 0:38:06

在这里插入图片描述
微信登录的appId获得可在微信开放平台申请,以下用测试号

1、完成WeixinProperties

用测试账号登录

public class WeixinProperties {

	private String appId = "wxd99431bbff8305a0";
	private String appSecret = "60f78681d063590a469f1b297feff3c4";
	
	private String prividerId = "weixin";
	private String filterProcessesUrl = "/qqLogin";
	
	//get/set
}
package com.zzz.blog.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "blog.security")
public class BlogSecurityProperties {
	
	private WeixinProperties weixinProperties = new WeixinProperties();
		
	//get/set
}
package com.zzz.blog.properties;

import ...

@Configuration
//让我们的配置生效
@EnableConfigurationProperties (BlogSecurityProperties.class)
public class BlogSecurityConfig {
	
}

2、创建微信包和api的功能

在这里插入图片描述
微信signup包与qq登录的signup共享一份文件(查看前面qq登录的文章)

package com.zzz.blog.social.weixin.api;

public interface Weixin {

	WeixinUserInfo getUserInfo(String openId);
}
package com.zzz.blog.social.weixin.api;

public class WeixinUserInfo {

	private String language;
	private String openid;
	private String nickname;
	private String sex;
	private String province;
	private String city;
	private String country; 
	private String headimgurl;
	private String[] privilege;
	private String unionid;
	
	//get/set
	
}

3、完成WeixinImpl的实现

package com.zzz.blog.social.weixin.api;

import ...

public class WeixinImpl extends AbstractOAuth2ApiBinding implements Weixin{

	private static final String URL_GET_USERINFO = "https://api.weixin.qq.com/sns/userinfo?openid=";
	
	private ObjectMapper objectMapper = new ObjectMapper();
	
	//自动在url中拼接令牌
	public WeixinImpl(String accessToken) {
		super(accessToken,TokenStrategy.ACCESS_TOKEN_PARAMETER);
	}
	
	@Override
	public WeixinUserInfo getUserInfo(String openId) {

		String url = URL_GET_USERINFO + openId;
		//发送请求,获得weixinUserInfo数据
		String response = getRestTemplate().getForObject(url, String.class);
		
		WeixinUserInfo weixinUserInfo = null;
		
		try {
			weixinUserInfo = objectMapper.readValue(response, WeixinUserInfo.class);
		} catch (JsonProcessingException e) {
			throw new RuntimeException("json解析失败"+response);
		}
		
		return weixinUserInfo;
	}

	//解决收到的字符串是乱码,原因是,默认实现的HttpMessageConverter编码是ISO- 8859-1,而微信给我们的是UTF-8
	@Override
	protected List<HttpMessageConverter<?>> getMessageConverters() {

		List<HttpMessageConverter<?>> messageConverters = super.getMessageConverters();
		messageConverters.remove(0);
		messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
		return messageConverters;
	}

}

4、完成拼接获取令牌的请求,完成WeixinOAuth2Template

因微信获取令牌格式包含openid,需要重写获取令牌的方法

package com.zzz.blog.social.weixin.connect;

import ...

//微信特有的令牌,带openId
//正常的令牌是不带由openid的, 所以我们要自己实现一个特有的令牌
public class WeixinAccessGrant extends AccessGrant{

	private String openId;
	
	public WeixinAccessGrant(String accessToken, String scope, String refreshToken, Long expiresIn) {
		super(accessToken, scope, refreshToken, expiresIn);
		// TODO Auto-generated constructor stub
	}

	//get/set
}
package com.zzz.blog.social.weixin.template;

import ...

public class WeixinOAuth2Template extends OAuth2Template{

	private String accessTokenUrl;
	private String clientId;
	private String clientSecret;
	
	private ObjectMapper objectMapper = new ObjectMapper();
	
	private static final String REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token";
	
	public WeixinOAuth2Template(String clientId, String clientSecret, String authorizeUrl, String accessTokenUrl) {
		super(clientId, clientSecret, authorizeUrl, accessTokenUrl);
		
		this.accessTokenUrl = accessTokenUrl;
		this.clientId = clientId;
		this.clientSecret = clientSecret;
	}

	@Override
	public AccessGrant exchangeForAccess(String authorizationCode, String redirectUri,
			MultiValueMap<String, String> additionalParameters) {
		//获取accessTokenUrl
		StringBuilder accessTokenRequestUrl = new StringBuilder(accessTokenUrl);
		//拼接参数
		//https://api. weixin. qq. com/ sns/oauth2/access_ token
		// ?appid=APPID
		accessTokenRequestUrl.append("?appid="+clientId);
		//&secret=SECRET
		accessTokenRequestUrl.append("&secret="+clientSecret);
		//&code=CODE
		accessTokenRequestUrl.append("&code="+authorizationCode);
		//&grant_type=authorization_code
		accessTokenRequestUrl.append("&grant_type=authorization_code");
		//&redirect_uri=
		accessTokenRequestUrl.append("&redirect_uri="+redirectUri);
		
		return getAccessToken(accessTokenRequestUrl);
	}

	//发送请求,获取令牌
	private AccessGrant getAccessToken(StringBuilder accessTokenRequestUrl) {
		String response = getRestTemplate().getForObject(accessTokenRequestUrl.toString(), String.class);
//	{
//		"access_token": "ACCESS_ TOKEN",
//		"expires_in":7200,
//		"refresh_token": "REFRESH TOKEN",
//		'scope": "SCOPE",
//		"unionid": "o6_ bmasdasdsad6_ 2sgVt7hMZOPfL",
//		
//		"openid" : "OPENID"
//	}
		Map<String,Object> result = null;
		try {
			result = objectMapper.readValue(response, Map.class);
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException("objectMapper解析失败"+response);
		}
		//获得令牌
		WeixinAccessGrant accessToken = new WeixinAccessGrant(
				(String)result.get("access_token"),
				(String)result.get("scope"),
				(String)result.get("refresh_token"),
				new Long((Integer)result.get("expires_in")));
		accessToken.setOpenId((String)result.get("openid"));		
		//返回令牌
		return accessToken;
	}
	
	//解决收到的字符串是乱码
	@Override
	protected RestTemplate createRestTemplate() {
		RestTemplate template = super.createRestTemplate();
		template.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
		return template;
	}
	
	//当令牌失效后重新授权
	@Override
	public AccessGrant refreshAccess(String refreshToken, String scope,
			MultiValueMap<String, String> additionalParameters) {
		StringBuilder refreshTokenUrl = new StringBuilder(REFRESH_TOKEN_URL);
		//?appid=APPID
		refreshTokenUrl.append("?appid="+clientId);
		//&grant_type=refresh_token
		refreshTokenUrl.append("&grant_type=refresh_token");
		//&refresh_token=REFRESH_TOKEN
		refreshTokenUrl.append("&refresh_token="+refreshToken);
		
		return getAccessToken(refreshTokenUrl);
	}
	//授权的url
	@Override
	public String buildAuthenticateUrl(OAuth2Parameters parameters) {
		String url = super.buildAuthenticateUrl(parameters);
		url = url + "&appid=" + clientId + "&scope=snsapi_login";
		return url;
	}
}

5、完成WeixinServiceProvider与WeixinAdapter

package com.zzz.blog.social.weixin.connect;

import ...

public class WeixinServiceProvider extends AbstractOAuth2ServiceProvider<Weixin>{

	//获取授权码
	private static final String URL_AUTHORIZE="https://open.weixin.qq.com/connect/qrconnect";
	//获取令牌
	private static final String URL_ACCESS_TOKEN="https://api.weixin.qq.com/sns/oauth2/access_token";
	
	public WeixinServiceProvider(String appId,String appSecret) {
		super(new WeixinOAuth2Template(appId, appSecret, URL_AUTHORIZE, URL_ACCESS_TOKEN));
		// TODO Auto-generated constructor stub
	}

	@Override
	public Weixin getApi(String accessToken) {
		// TODO Auto-generated method stub
		return new WeixinImpl(accessToken);
	}
	
}
package com.zzz.blog.social.weixin.connect;

import ...

public class WeixinAdapter implements ApiAdapter<Weixin>{

	private String openId;
	
	public WeixinAdapter(String openId) {
		this.openId = openId;
	}

	@Override
	public boolean test(Weixin api) {
		//改为true
		return true;
	}

	//适配
	@Override
	public void setConnectionValues(Weixin api, ConnectionValues values) {
		WeixinUserInfo info = api.getUserInfo(openId);
		values.setDisplayName(info.getNickname());
		values.setProviderUserId(info.getOpenid());
		values.setImageUrl(info.getHeadimgurl());
	}

	@Override
	public UserProfile fetchUserProfile(Weixin api) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void updateStatus(Weixin api, String message) {
		// TODO Auto-generated method stub
		
	}

}

6、完成WeixinConnectionFactory

package com.zzz.blog.social.weixin.connect;

import ...

import com.zzz.blog.social.weixin.api.Weixin;

public class WeixinConnectionFactory extends OAuth2ConnectionFactory<Weixin>{

	public WeixinConnectionFactory(String providerId, String appId, String appSecret) {
		super(providerId, new WeixinServiceProvider(appId, appSecret), new WeixinAdapter());
		// TODO Auto-generated constructor stub
	}

	@Override
	public Connection<Weixin> createConnection(AccessGrant accessGrant) {
		// TODO Auto-generated method stub
		return new OAuth2Connection<>(getProviderId(),
				extractProviderUserId(accessGrant), 
				accessGrant.getAccessToken(), 
				accessGrant.getRefreshToken(), 
				accessGrant.getExpireTime(), 
				getOAuth2ServiceProvider(), 
				getApiAdapter(extractProviderUserId(accessGrant)));
	}

	@Override
	public Connection<Weixin> createConnection(ConnectionData data) {
		return new OAuth2Connection<>(data, getOAuth2ServiceProvider(), getApiAdapter(data.getProviderUserId()));
	}

	@Override
	protected String extractProviderUserId(AccessGrant accessGrant) {
		if(accessGrant instanceof WeixinAccessGrant) {
			return ((WeixinAccessGrant)accessGrant).getOpenId();
		}
		return null;
	}

	public OAuth2ServiceProvider<Weixin> getOAuth2ServiceProvider() {
		return (OAuth2ServiceProvider<Weixin>)getServiceProvider();
	}

	public ApiAdapter<Weixin> getApiAdapter(String providerUserId) {
		return new WeixinAdapter(providerUserId);
	}
	
}

7、完成WeixinConfiguration

package com.zzz.blog.social.weixin.config;

import ...

@Configuration
@EnableSocial
public class WeixinConfiguration extends SocialConfigurerAdapter{
	
	@Autowired
	private BlogSecurityProperties blogSecurityProperties;

	@Override
	public void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer,
			Environment environment) {
		WeixinProperties weixinProperties = blogSecurityProperties.getWeixinProperties();
		WeixinConnectionFactory weixinConnectionFactory = new WeixinConnectionFactory(weixinProperties.getPrividerId(), weixinProperties.getAppId(), weixinProperties.getAppSecret());
		connectionFactoryConfigurer.addConnectionFactory(weixinConnectionFactory);
	}
	
}
<a href="/qqLogin/weixin" class="login100-social-item bg1">
							<i class="fa fa-wechat"></i>
						</a>

8、完成添加数据表visitor和表userconnection

package com.zzz.blog.social.qq.config;

import javax.sql.DataSource;

import ...

@Configuration
@EnableSocial
@Order(1)
public class SocialConfig extends SocialConfigurerAdapter{
	
	@Autowired
	private DataSource dataSource;
	
	@Autowired
	private BlogSecurityProperties blogSecurityProperties;
	
	@Autowired
	private ConnectionFactoryLocator connectionFactoryLocator;
	
	@Autowired
	private ConnectionSignUp connectionSignUp;
	
	//打开ConnectController
	@Bean
	public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator,ConnectionRepository connectionRepository) {
		return new ConnectController(connectionFactoryLocator, connectionRepository);
	}
	//登录之后,直接将QQ或微信的数据保存在数据库,保存在usersconnection表和visitor表中
	@Override
	public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
		JdbcUsersConnectionRepository repository = new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator, Encryptors.noOpText());
		repository.setConnectionSignUp(connectionSignUp);
		return repository;
	}	
	
	//改变拦截的请求 /auth -> /qqLogin,注入到SecurityConfig中
	@Bean
	public SpringSocialConfigurer zzzSocialSecurityConfig() {
		String filterProcessesUrl = blogSecurityProperties.getQqProperties().getFilterProcessesUrl();
		ZZZSpringSocialConfigurer zzzSpringSocialConfigurer = new ZZZSpringSocialConfigurer(filterProcessesUrl);
		return zzzSpringSocialConfigurer;
	}
	
	//在注册的过程中,拿到了这个SpringSocial中的信息
	//业务完成之后,把用户的id传给了SpringSocial
	@Bean
	public ProviderSignInUtils providerSignInUtils() {
		return new ProviderSignInUtils(connectionFactoryLocator, getUsersConnectionRepository(connectionFactoryLocator));
	}
}	

使zzzSocialSecurityConfig生效

package com.zzz.blog.config;

import ...

//安全配置类
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	//SpringSecurity加密方法返回值
	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	
	@Autowired
	private SpringSocialConfigurer zzzSocialSecurityConfig;
	
	//做拦截
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// 请求授权
		http.formLogin().and().authorizeRequests()
		//授权放行
		.antMatchers("/visitorLogin","/index","/mood","/findMood","/findAllBlog","/findAllAlbum","/findAllArchives","/link",
				"/css/**","/editor.md/**","/images/**","/js/**","/layer/**","/social/**","/statics/**","/upload/**").permitAll()
		//所有请求
		.anyRequest()
		//都需要身份认证
		.authenticated().and()
		//43、使用Layer打开select-mood子页面并配置SpringSecurity允许Iframe嵌入页面 
		.headers().frameOptions().disable().and()
		//跨站请求伪造的防护
		.csrf().disable()
		//添加我们所写的spring social配置
		.apply(zzzSocialSecurityConfig);
	}
	
}
package com.zzz.blog.social.qq.config;

import ...

public class ZZZSpringSocialConfigurer extends SpringSocialConfigurer{

	private String filterProcessesUrl;

	public ZZZSpringSocialConfigurer(String filterProcessesUrl) {
		this.filterProcessesUrl = filterProcessesUrl;
	}

	
	//将默认的拦截改为qqLogin
	@Override
	protected <T> T postProcess(T object) {
		//获得filter
		SocialAuthenticationFilter filter = (SocialAuthenticationFilter)super.postProcess(object);
		//设置字段
		filter.setFilterProcessesUrl(filterProcessesUrl);
		return (T) filter;
	}
	
}

创建Jdbc的userconnection表,在mysql中执行

create table UserConnection (userId varchar(255) not null,
	providerId varchar(255) not null,
	providerUserId varchar(255),
	rank int not null,
	displayName varchar(255),
	profileUrl varchar(512),
	imageUrl varchar(512),
	accessToken varchar(512) not null,
	secret varchar(512),
	refreshToken varchar(512),
	expireTime bigint,
	primary key (userId, providerId, providerUserId));
create unique index UserConnectionRank on UserConnection(userId, providerId, rank);

visitor的创建

@Entity
public class Visitor {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	private String username;
	private String password;
	private String image;

	//get/set
}
package com.zzz.blog.social.qq.signup;

import ...

@Component
public class DemoConnectionSignUp implements ConnectionSignUp{

	@Autowired
	private VisitorService visitorService;
	
	//根据社交用户的信息,创建一个Visitor并返回唯一标识
	@Override
	public String execute(Connection<?> connection) {
		
		Visitor visitor = new Visitor(null, connection.getDisplayName(), "123456", connection.getImageUrl());
		
		visitor = visitorService.saveVisitory(visitor);
		
		return visitor.getId().toString();
	}

}
package com.zzz.blog.service;

import ...

@Component
public class VisitorServiceImpl implements VisitorService{

	@Autowired
	private VisitorRepository visitorRepository;
	
	@Override
	public Visitor saveVisitory(Visitor visitor) {
		return visitorRepository.save(visitor);
	}

}
package com.zzz.blog.service;

import ...

@Service
public interface VisitorService {

	Visitor saveVisitory(Visitor visitor);

}

10、完成测试登录

因为使用测试号,系统修改hosts

127.0.0.1   www.pinzhi365.com

application.properties文件修改端口

server.port=80

登录后visitor表和userconnection表都获得用户数据。

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

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

相关文章

基于SSM+Vue的医学生在线学习交流平台

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

【数字人】1、SadTalker | 使用语音驱动单张图片合成视频(CVPR2023)

Sad Talker&#xff1a;使用一张图片和一段语音来生成口型和头、面部视频 论文&#xff1a;SadTalker: Learning Realistic 3D Motion Coefficients for Stylized Audio-Driven Single Image Talking Face Animation 代码&#xff1a;https://github.com/Winfredy/SadTalker …

Linux命令200例:dip用于用户与远程主机建立通信连接

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0…

Stable DIffusion 炫酷应用 | AI嵌入艺术字+光影光效

目录 1 生成AI艺术字基本流程 1.1 生成黑白图 1.2 启用ControlNet 参数设置 1.3 选择大模型 写提示词 2 不同效果组合 2.1 更改提示词 2.2 更改ControlNet 2.2.1 更改模型或者预处理器 2.2.2 更改参数 3. 其他应用 3.1 AI光影字 本节需要用到ControlNet&#xff0c;可…

6.前端·新建子模块与开发(常规开发)

文章目录 学习资料常规开发创建组件与脚本菜单创建-新增自定义图标菜单创建-栏目创建 学习资料 https://www.bilibili.com/video/BV13g411Y7GS?p12&vd_sourceed09a620bf87401694f763818a31c91e 常规开发 创建组件与脚本 首先新建前端的目录结构&#xff0c;属于自己业…

CTF 全讲解:[SWPUCTF 2022 新生赛]webdog1__start

文章目录 参考环境题目learning.php信息收集isset()GET 请求查询字符串全局变量 $_GET MD5 绕过MD5韧性脆弱性 md5()弱比较隐式类型转换字符串连接数学运算布尔判断 相等运算符 MD5 绕过科学计数法前缀 0E 与 0e绕过 start.php信息收集头部检索 f14g.php信息收集 探秘 F1l1l1l1…

Springboot 实践(18)Nacos配置中心参数自动刷新测试

前文讲解了Nacos 2.2.3配置中心的服务端的下载安装&#xff0c;和springboot整合nacos的客户端。Springboot整合nacos关键在于使用的jar版本要匹配&#xff0c;文中使用版本如下&#xff1a; ☆ springboot版本: 2.1.5.RELEASE ☆ spring cloud版本 Greenwich.RELEASE ☆ sp…

Python 算数运算符

视频版教程 Python3零基础7天入门实战视频教程 Python支持所有的基本算术运算符&#xff0c;这些算术运算符用于执行基本的数学运算&#xff0c;如加、减、乘、除和求余等。下面是7个基本的算术运算符。 以下&#xff0c;假设变量a为10&#xff0c;变量b为21&#xff1a; 实…

OpenCV之YOLOv3目标检测

&#x1f482; 个人主页:风间琉璃&#x1f91f; 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主&#x1f4ac; 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦 目录 前言 一、预处理 1.获取分类名 2.获取输出层名称 3.图像尺度变换 二…

【JavaSE笔记】初识Java

一、前言 Java是一种非常优秀的程序设计语言&#xff0c;它具有令人赏心悦目的语法和易于理解的语义。 本文将通过一个简单的Java程序&#xff0c;介绍Java的一些基础内容。 二、Java基本结构 1、简单的Java程序 从最简单的一个Java程序开始逐渐了解Java语言。 以下是一段…

数学建模——微分方程介绍

一、基础知识 1、一阶微分方程 称为一阶微分方程。y(x0)y0为定解条件。 其常规求解方法&#xff1a; &#xff08;1&#xff09;变量分离 再两边积分就可以求出通解。 &#xff08;2&#xff09;一阶线性求解公式 通解公式&#xff1a; 有些一阶微分方程需要通过整体代换…

echarts的折线图,在点击图例后,提示出现变化,不报错。tooltip的formatter怎么写

在点击图例的年后&#xff0c;提示框会相应的变化&#xff0c;多选和单选都会响应变化。tooptip的重度在formatter tooltip:{show:true,trigger:"axis",alwaysShowContent:true,triggerOn:"mousemove",textStyle:{color:"#fff"},backgroundColor…

结构体-时间的计算

任务描述 本关任务需要你编写函数计算一个时间之前“xx小时xx分xx秒”的时间是多少。 以24小时制的格式记录当前时间&#xff0c;譬如“09:19:52”&#xff0c;表示上午9点19分52秒&#xff0c;则“1小时20分30秒”前的时间应该是“同一天”的“07:59:22”。 提示&#xff1a;…

Scapy 解析 pcap 文件从HTTP流量中提取图片

Scapy 解析 pcap 文件从HTTP流量中提取图片 前言一、网络环境示例二、嗅探流量示例三、pcap 文件处理最后参考 ​ 作者&#xff1a;高玉涵 ​ 时间&#xff1a;2023.9.17 10:25 ​ 环境&#xff1a;Linux kali 5.15.0-kali3-amd64&#xff0c;Python 3.11.4&#xff0c;scapy…

解决Springboot使用Junit测试时对数据库的修改无效

现象 在使用Junit做单元测试的过程中&#xff0c;比如对mybatis的dao进行单元测试&#xff0c;发现对数据库的select操作正常&#xff0c;可以获取数据&#xff0c;但insert、update、delete操作即使运行不报错&#xff0c;仍然不能不能对数据产生修改和插入。 原因和解决 原…

d3dx9_42.dll丢失修复指南,如何修复丢失的d3dx9_42.dll文件

d3dx9_42.dll是DirectX 9的一个动态链接库文件&#xff0c;它是许多游戏和软件的必需组件。如果缺少这个文件&#xff0c;可能会导致程序无法正常运行。本文将详细讲解d3dx9_42.dll的作用以及丢失的原因&#xff0c;并提供5种修复方法。 一、d3dx9_42.dll的作用 1. d3dx9_42.d…

IDEA创建完Maven工程后,右下角一直显示正在下载Maven插件

原因&#xff1a; 这是由于新建的Maven工程&#xff0c;IDEA会用它内置的默认的Maven版本&#xff0c;使用国外的网站下载Maven所需的插件&#xff0c;速度很慢 。 解决方式&#xff1a; 每次创建 Project 后都需要设置 Maven 家目录位置&#xff08;就是我们自己下载的Mav…

操作系统学习笔记-精简复习版

文章目录 操作系统概述1、操作系统2、主要功能3、用户态和内核态4、系统调用 进程管理1、进程和线程2、引入线程的好处3、线程间同步4、进程控制块 PCB5、进程的状态6、进程的通信方式7、进程的调度算法8、僵尸进程&孤儿进程9、死锁 内存管理1、内存碎片2、内存管理3、虚拟…

2023面试知识点一

1、新生代和老年代的比例 默认的&#xff0c;新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 )&#xff0c;即&#xff1a;新生代 ( Young ) 1/3 的堆空间大小。老年代 ( Old ) 2/3 的堆空间大小。其中&#xff0c;新生代 ( …

WebGoat搭建和Yakit学习

环境搭建 jdk版本&#xff1a;openjdk version "17.0.5“ WebGoat版本&#xff1a;webgoat-server-8.1.0.jar 环境不同有很大可能不能搭建成功 运行命令&#xff1a;java -jar webgoat-server-8.1.0.jar --server.port8888 --server.address192.168.142.131 搭建完成后…