Spring——Security安全框架使用详解(基于内存认证)_专注写bug的博客-程序员宝宝

技术标签: spring  spring security  java  安全  

前言

在日常开发中,几乎所有的项目都需要进行请求的安全校验操作。

通常会采取以下几种方式来实现安全校验过滤

Security简介

在这里插入图片描述

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是保护基于Spring的应用程序的事实标准。
Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring Security的真正威力在于它可以多么容易地扩展以满足定制需求。

Spring Security 官方文档

Security相关模块

  • 核心模块spring-security-core.jar。包含核心验证和访问控制类接口,远程支持的基本配置API。任何使用Spring Security的应用程序都需要这个模块。支持独立应用程序、远程客户端、服务层方法安全和JDBC用户配置。
    包含以下顶层包:
    • org.springframework.security.core
    • org.springframework.security.access
    • org.springframework.security.authentication
    • org.springframework.security.provisioning
  • 远程调用spring-security-remoting.jar。提供与 Spring Remoting 集成。
    主要包为:org.springframework.security.remoting
  • 网页spring-security-web.jar。包括网站安全的模块,提供网站认证服务和基于 URL 访问控制。
    主包名为 org.springframework.security.web
  • 配置spring-security-config.jar。包含安全命令空间的解析代码。如果你使用Spring Security XML命令空间进行配置你需要包含这个模块。 主包名为org.springframework.security.config
  • LDAPspring-security-ldap.jar。LDAP验证和配置代码,如果你需要使用LDAP验证和管理LDAP用户实体,你需要这个模块。
    主包名为 org.springframework.security.ldap
  • ACL访问控制表spring-security-acl.jar。ACL专门的领域对象的实现。用来在你的应用程序中应用安全特定的领域对象实例。
    主包名为 org.springframework.security.acls
  • CASspring-security-cas.jar。Spring Security的CAS客户端集成。如果你想用CAS的SSO服务器使用Spring Security网页验证需要该模块。
    顶层的包是 org.springframework.security.cas
  • OpenIDspring-security-openid.jar。OpenID 网页验证支持。使用外部的OpenID服务器验证用户。 org.springframework.security.openid. 需要 OpenID4Java
  • Testspring-security-test.jar。支持Spring Security的测试。

选于:security 官方文档 模块

配置和初试

本篇博客基于 SpringBoot 技术架构实现配置和使用操作,配置方式采取IEAD中的Maven 父子项目格式进行搭建。

父项目依赖引入

创建Maven父工程,配置整体测试环境的依赖版本管控。

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <junit.version>4.12</junit.version>
    <log4j.version>1.7.25</log4j.version>
    <lombok.version>1.16.18</lombok.version>

    <spring.boot.version>2.2.2.RELEASE</spring.boot.version>

</properties>

<parent>
  <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.4.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>${spring.boot.version}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>${lombok.version}</version>
</dependency>
<!--日志打印-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>${log4j.version}</version>
</dependency>

创建子项目工程

关于如何创建父子项目,本次不做过多说明。

可以看考博客:idea中Springboot项目如何做成父子结构

子项目中,引入具体的依赖:

<dependency>
 	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-test -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
</dependency>

启动子项目,访问http://localhost:8080/观察现象:
在这里插入图片描述
在这里插入图片描述
此处会自动进入一个登录界面!!!

创建一个新的controller接口,重启项目,然后请求接口测试:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    

    @RequestMapping("/test1")
    public String test1(){
    
        return "test1";
    }
}

http://localhost:8080/test1

访问后,依旧是当前的登录界面,此时登录账户密码信息为:

  • 账户:user
  • 密码:控制台中的随机uuid值

在这里插入图片描述
在这里插入图片描述
这种情况是由于security框架,默认生成当前登录密码,存于内存中,进行实现。

但并不适合实际开发使用!

security 登录账户密码修改、配置(基于内存)

security框架在开发者本身未对其进行设定时,默认登录账户为user,密码为随机uuid,生成并存于内存中。

如果想要设定指定的账号密码进行访问控制,可以采取如下几种方式实现:

配置文件指定账户密码(了解)

创建一个application.yaml的文件,在其中增加如下配置信息:

spring:
  security:
    user:
      name: xiangjiao
      password: bunana

重启项目,重新访问http://localhost:8080/test1,跳转指定的登录界面,输入配置的用户名和密码信息:
在这里插入图片描述
在这里插入图片描述
通过源码org.springframework.boot.autoconfigure.security.SecurityProperties类,可以知道其默认的账户、密码生成方式:
在这里插入图片描述

但是针对实际的开发逻辑来看,定义死板的方式,并不适合实际的开发需要。

正常来说,验证登录信息,需要从数据库中获取指定账户的账号、密码等。

编写服务类验证登录账户、密码(了解)

security框架中,与其作用相关的配置信息,都是采取org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration配置类实现配置信息的加载,源码中,针对这个类的描述信息如下所示:
在这里插入图片描述
从上图中可以发现:

SecurityAutoConfiguration自动配置类,依赖有几个其他的配置文件。

其中,针对于验证的配置类为:org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration
在这里插入图片描述
其次,spring security框架本身给开发使用者提供了很多的其他工具类,来实现用户认证操作,如:基于内存基于jdbc等。

org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration
在这里插入图片描述
在这里插入图片描述

实际测试代码编写

编写一个UserServiceImpl.java类,用于实现UserDetailsService,并使用重写其中的loadUserByUsername实现具体的认证操作

import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

@Component // 由spring管理
public class UserServiceImpl implements UserDetailsService {
    

    // 加载用户信息
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    
        // 需要返回  UserDetails 对象实例,
        // 查看 UserDetails接口 下的几个子实现类,可以发现有几种类型
        // 使用 org.springframework.security.core.userdetails.User 这个子类
        UserDetails userDetails = new User("xiangjiao","bunana", 
                AuthorityUtils.commaSeparatedStringToAuthorityList("add,rm"));

        return userDetails;
    }
}

重启项目,重新请求http://localhost:8080/test1,输入用户名和密码信息。

发现:并没有进行跳转!

查看控制台,日志打印信息如下所示:
在这里插入图片描述
【问题分析:】

出现java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"问题的原因在于:
security 4之后,官方对密码编码器进行了修改操作。

查看org.springframework.security.crypto.factory.PasswordEncoderFactories源码可以知道security对其提供很多的编码方式。
在这里插入图片描述
如果需要使用其中的指定编码,实现登录验证测试,则需要将设定密码进行编码转换。

转换后如下所示:{noop}xxx表示无加密

import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

@Component // 由spring管理
public class UserServiceImpl implements UserDetailsService {
    

    // 加载用户信息
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    
        // 需要返回  UserDetails 对象实例,
        // 查看 UserDetails接口 下的几个子实现类,可以发现有几种类型
        // 使用 org.springframework.security.core.userdetails.User 这个子类
        UserDetails userDetails = new User("xiangjiao","{noop}bunana",
                AuthorityUtils.commaSeparatedStringToAuthorityList("add,rm"));

        return userDetails;
    }
}

重启项目,重新请求http://localhost:8080/test1,发现:

输入用户名、密码后,能够成功跳转。

如果设定加密,则可以按照如下方式配置。

import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Component;

@Component // 由spring管理
public class UserServiceImpl implements UserDetailsService {
    

    // 加载用户信息
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    
        // 需要返回  UserDetails 对象实例,
        // 查看 UserDetails接口 下的几个子实现类,可以发现有几种类型
        // 使用 org.springframework.security.core.userdetails.User 这个子类

        // 无加密
//        UserDetails userDetails = new User("xiangjiao","{noop}bunana",
//                AuthorityUtils.commaSeparatedStringToAuthorityList("add,rm"));

        // 有加密
        String encryptPwd = BCrypt.hashpw("bunana",BCrypt.gensalt());
        UserDetails userDetails = new User("xiangjiao","{bcrypt}"+encryptPwd,
                AuthorityUtils.commaSeparatedStringToAuthorityList("add,rm"));

        return userDetails;
    }
}

重启项目,重新请求http://localhost:8080/test1。输入对应的账号、密码信息后,能够成功验证通过。

但是,这种方式一般使用率较低!

每次都需要针对具体的加密解密方式,拼接{bcrypt}等太麻烦。

可以考虑使用org.springframework.security.crypto.factory.PasswordEncoderFactories中的一种加解密,进行注入使用。下面进行相关测试。

采取配置类方式实现校验

上面的操作中,采取BCrypt.hashpw("bunana",BCrypt.gensalt())将密码进行加密操作,随后拼接 {bcrypt}的形式,封装至org.springframework.security.core.userdetails.User对象实例中,过于繁琐,可以采取如下方式进行设定:

创建一个配置类:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;


 开启 Security ,
// 但是在 org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration 中的
// org.springframework.boot.autoconfigure.security.servlet.WebSecurityEnablerConfiguration 类上
// 已经标注 @EnableWebSecurity

 @EnableWebSecurity   // 此处不需要该注解进行开启
@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    

     /**
      * 申明 {bcrypt} 对应的 BCryptPasswordEncoder 密码编码器 bean 对象;
      * 在进行 cn.security.service.UserServiceImpl#loadUserByUsername(java.lang.String) 时,注入使用
      * @return
      */
     @Bean
     public PasswordEncoder passwordEncoder(){
    
         return new BCryptPasswordEncoder();
     }
}

创建一个服务类,实现UserDetailsService,重写loadUserByUsername

并将已创建bean,进行注入其中。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

/**
 * 自定义身份验证服务类
 */
@Component
public class UserAuthenticationServiceImpl implements UserDetailsService {
    

    // 注入申明的 PasswordEncoder 密码解析器
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    
        // 需要返回 UserDetail 实例
        UserDetails userDetails = new User("xiangjiao",passwordEncoder.encode("bunana"),
                AuthorityUtils.commaSeparatedStringToAuthorityList("add,rm"));
        return userDetails;
    }
}

将项目重启,进行测试:

http://localhost:8080/test1

在这里插入图片描述
在这里插入图片描述
【联想:】这里都可以采取注入的方式实现了,也就是说可以注入一个数据库的查询mapper?

方式三:重写userDetailsServiceBean加载自定义service

除了上面的UserAuthenticationServiceImpl,将其交给Spring管理之外,也能够采取手动配置的方式将UserAuthenticationServiceImpl加载。用来时间验证操作,如下所示:

创建service文件:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;

// 这里没有交给spring管理
public class UserAuthenticationServiceImpl implements UserDetailsService {
    

    // 注入申明的 PasswordEncoder 密码解析器
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    
        // 需要返回 UserDetail 实例
        // passwordEncoder.encode("bunana") 会自动进行密码的加密和解析操作
        UserDetails userDetails = new User("xiangjiao",passwordEncoder.encode("bunana"),
                AuthorityUtils.commaSeparatedStringToAuthorityList("add,rm"));
        return userDetails;
    }
}

创建对应的配置类:

import cn.security.service.UserAuthenticationServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

 开启 Security ,
// 但是在 org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration 中的
// org.springframework.boot.autoconfigure.security.servlet.WebSecurityEnablerConfiguration 类上
// 已经标注 @EnableWebSecurity
//@EnableWebSecurity
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    


    /**
     * 申明 {bcrypt} 对应的 BCryptPasswordEncoder 密码编码器 bean 对象;
     * 在进行 cn.security.service.UserServiceImpl#loadUserByUsername(java.lang.String) 时,注入使用
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
    
        return new BCryptPasswordEncoder();
    }

    /**
     * 方式三:重写 WebSecurityConfigurerAdapter 中的 userDetailsServiceBean。<br/>
     * 官方推荐使用 userDetailsServiceBean
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public UserDetailsService userDetailsServiceBean() throws Exception {
    
    	// 采取手动实例化 指定的 UserAuthenticationServiceImpl 方式
        return new UserAuthenticationServiceImpl();
    }
}

具体参考gitee中的代码项目 -- springboot-security-02

启动项目,重新访问:

http://localhost:8080/test1

在这里插入图片描述
在这里插入图片描述

方式四:重写 WebSecurityConfigurerAdapter 中的configure方法

参考:springboot-security-03

基于内存

在配置类中,重写 ``WebSecurityConfigurerAdapter中的configure

package cn.security.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

 开启 Security ,
// 但是在 org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration 中的
// org.springframework.boot.autoconfigure.security.servlet.WebSecurityEnablerConfiguration 类上
// 已经标注 @EnableWebSecurity
//@EnableWebSecurity
@Configuration
public class MyConfig extends WebSecurityConfigurerAdapter {
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
        // 基于内存配置
        auth.inMemoryAuthentication() 
                .withUser("xiangjiao")
                .password(passwordEncoder().encode("bunana"))
                .authorities("admin")
                .and()
                .withUser("123")
                .password(passwordEncoder().encode("123456"))
                .authorities("role");
    }

    /**
     * 申明 {bcrypt} 对应的 BCryptPasswordEncoder 密码编码器 bean 对象;
     * 在进行 cn.security.service.UserServiceImpl#loadUserByUsername(java.lang.String) 时,注入使用
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
    
        return new BCryptPasswordEncoder();
    }
}

在这里插入图片描述
请求连接,进行测试:

http://localhost:8080/test

在这里插入图片描述
在这里插入图片描述


基于userDetailService

除了基于 内存方式之外,还有其他的配置方式,如下所示:
基于 userDetailService实现。

修改配置类,增加userDetailService的实现,如下所示:

package cn.security.config;

import cn.security.service.UserAuthenticationServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

 开启 Security ,
// 但是在 org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration 中的
// org.springframework.boot.autoconfigure.security.servlet.WebSecurityEnablerConfiguration 类上
// 已经标注 @EnableWebSecurity
//@EnableWebSecurity
@Configuration
public class MyConfig extends WebSecurityConfigurerAdapter {
    

    /**
     * 由于交给spring进行管理bean的生命周期,此处可以直接注入
     */
    @Autowired
    private UserAuthenticationServiceImpl userAuthenticationService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
        // 基于内存配置
//        auth.inMemoryAuthentication()
//                .withUser("xiangjiao")
//                .password(passwordEncoder().encode("bunana"))
//                .authorities("admin")
//                .and()
//                .withUser("123")
//                .password(passwordEncoder().encode("123456"))
//                .authorities("role");

        // 基于   userDetailService
        // UserAuthenticationServiceImpl 实现  UserDetailsService,可以直接传递
        auth.userDetailsService(userAuthenticationService);
    }

    /**
     * 申明 {bcrypt} 对应的 BCryptPasswordEncoder 密码编码器 bean 对象;
     * 在进行 cn.security.service.UserServiceImpl#loadUserByUsername(java.lang.String) 时,注入使用
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
    
        return new BCryptPasswordEncoder();
    }
}

增加UserAuthenticationServiceImpl这个UserDetailsService的子实现类:

package cn.security.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;


@Component  // 交给spring管理
public class UserAuthenticationServiceImpl implements UserDetailsService {
    

    // 注入申明的 PasswordEncoder 密码解析器
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    
        // 需要返回 UserDetail 实例
        // passwordEncoder.encode("bunana") 会自动进行密码的加密和解析操作
        UserDetails userDetails = new User("xiangjiao",passwordEncoder.encode("bunana"),
                AuthorityUtils.commaSeparatedStringToAuthorityList("add,rm"));
        return userDetails;
    }
}

当然,UserAuthenticationServiceImpl也可以不交给Spring管理,此时则需要采取new的方式创建。

项目整体布局如下所示:
在这里插入图片描述
项目运行后,请求测试:

http://localhost:8080/test

在这里插入图片描述
在这里插入图片描述

代码参考

gitee 仓库

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_38322527/article/details/122998264

智能推荐

C语言 编译和链接_c语言连接_十七ing的博客-程序员宝宝

本篇博客介绍了 C语言 的编译和链接,并在后续主要介绍了编译部分。

DSP中断/BIOS_vincent_zou的博客-程序员宝宝

TMS320C54x系列DSP中的应用 摘要:详细分析了TMS320C54x系列DSP的中断机制,以及在扩展地址模式下中断控制所具有的一些特点,并给出了DSP/BIOS下中断的管理。   关键词:中断 中断向量表 TMS320C54x DSP/BIOS DSP中断是嵌入式芯片的灵魂,这是因为多数嵌入式系统对实时性都有很高的要求,即对出现事件的

Spring-session+mongodb实现session共享_Himly_Zhang的博客-程序员宝宝

Spring-session+mongodb实现session共享pom.xml配置web.xml配置applicationContext.xml 核心配置文件在系统中使用sessionpom.xml配置首先需要引入依赖包,直接在pom.xml中添加以下代码即可。 &amp;amp;lt;!-- spring-session整合mongodb --&amp;amp;gt; &amp;amp;lt;dependency&amp;amp;gt; ...

随便推点

Spark(五十):使用JvisualVM监控Spark Executor JVM_weixin_30545285的博客-程序员宝宝

引导Windows环境下JvisulaVM一般存在于安装了JDK的目录${JAVA_HOME}/bin/JvisualVM.exe,它支持(本地和远程)jstatd和JMX两种方式连接远程JVM。jstatd (Java Virtual Machine jstat Daemon)——监听远程服务器的CPU,内存,线程等信息JMX(Java Management Extensions...

Socket编程项目VS开发环境配置_༄yi笑奈何的博客-程序员宝宝

项目属性-&amp;gt;连接器-&amp;gt;输入-&amp;gt;附加依赖项里加入ws2_32.lib

零基础手把手教你学会Webpack(一)_webpack -v不是内部命令_世态炎凉!!的博客-程序员宝宝

文章目录1.前言2.Webpack是什么?有什么用?3.为什么选择Webpack?webpack的优势在哪?3. 如何安装 webpack?4. entry,chunk,bundle是什么?4.1 entry4.2 chunk4.3 bundle5.资源入口6. webpack入门应用6. path的join和resolve区别6.1 path.join6.2 path.resolve1.前言上一篇文章说了一篇文章带你玩转前端所有模块化,有了模块化,那么肯定需要模块化打包工具,那么从这一篇文章开始,我将

第一次参加Spring-MVC项目心得_spring mvc小项目心得_秋名山山妖的博客-程序员宝宝

Tomcat启动时启动监听器在Tomcat启动时,随即执行相关的逻辑。编写监听器代码创建TomcatListener:public class TomcatListener implements ServletContextListener并重写以下两个方法:public void contextInitialized(ServletContextEvent servletConte...

Java源码——使用JFileChooser获取文件及目录信息(Obtain file and directory information)_预见未来to50的博客-程序员宝宝

代码如下:1. FileAndDirectoryInfo类(获取文件及目录信息)// Fig. 15.2: FileAndDirectoryInfo.java// File class used to obtain file and directory information.package ch15;import java.io.IOException;import java.n

jena-fuseki 在线更新数据库_Fu_Tianshu的博客-程序员宝宝

fuseki 在线更新数据库命令:s-update --service=http://localhost:3030/ds/update --file=update.rufuseki 的官网上写的命令是 s-update --service http://localhost:3030/ds/update --file=update.ru,其中--service之后没有写“=”,有误。

推荐文章

热门文章

相关标签