系列博文

  项目已上传至guthub  传送门

  JavaWeb-SpringSecurity初认识  传送门

  JavaWeb-SpringSecurity在数据库中查询登陆用户  传送门

  JavaWeb-SpringSecurity自定义登陆页面  传送门

  JavaWeb-SpringSecurity实现需求-判断请求是否以html结尾  传送门

  JavaWeb-SpringSecurity自定义登陆配置  传送门

  JavaWeb-SpringSecurity图片验证ImageCode  传送门

  JavaWeb-SpringSecurity记住我功能  传送门

  JavaWeb-SpringSecurity使用短信验证码登陆  传送门

  在MySQL数据库中创建springsecurity数据库

  

  (id、username、password都是根据User.java映射过来的)

  在application.properties中编写配置文件

#datasource
spring.datasource.url=jdbc:mysql:///springsecurity?serverTimezone=UTC&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.dricer-class-name=com.mysql.jdbc.Driver #jpa
#打印出数据库语句
spring.jpa.show-sql=true
#更新数据库表
spring.jpa.hibernate.ddl-auto=update

  创建domain实体层User.java和repository存储层接口UserRepository.java  

  书写用户User.java实体

    //用户是否没有失效
@Transient
private boolean accountNonExpried;
//用户是否冻结
@Transient
private boolean accountNonLocked;
//证明是否过期
@Transient
private boolean credentialsNonExpired;
//判断是否删除
@Transient
private boolean enabled;
@Transient
//添加 @Transient 注解可以不将 Set<GrantedAuthority>映射到数据库表上
private Set<GrantedAuthority> authorities; //给hibernatre用的构造方法
protected User() { } public User(Long id,String username,String password)
{
this.id = id;
this.username = username;
this.password = password;
} //给SpringSecurity用的构造方法
public User(String username,String password,
Collection<? extends GrantedAuthority> authorities) {
this(username,password,true,true,true,true,authorities);
} public User(String username, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) { if (((username == null) || "".equals(username)) || (password == null)) {
throw new IllegalArgumentException(
"Cannot pass null or empty values to constructor");
} this.username = username;
this.password = password;
this.enabled = enabled;
this.accountNonExpried = accountNonExpired;
this.credentialsNonExpired = credentialsNonExpired;
this.accountNonLocked = accountNonLocked;
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
} private static SortedSet<GrantedAuthority> sortAuthorities(
Collection<? extends GrantedAuthority> authorities) {
Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
// Ensure array iteration order is predictable (as per
// UserDetails.getAuthorities() contract and SEC-717)
SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<>(
new AuthorityComparator()); for (GrantedAuthority grantedAuthority : authorities) {
Assert.notNull(grantedAuthority,
"GrantedAuthority list cannot contain any null elements");
sortedAuthorities.add(grantedAuthority);
} return sortedAuthorities;
} private static class AuthorityComparator implements Comparator<GrantedAuthority>,
Serializable {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; public int compare(GrantedAuthority g1, GrantedAuthority g2) {
// Neither should ever be null as each entry is checked before adding it to
// the set.
// If the authority is null, it is a custom authority and should precede
// others.
if (g2.getAuthority() == null) {
return -1;
} if (g1.getAuthority() == null) {
return 1;
} return g1.getAuthority().compareTo(g2.getAuthority());
}
}
package com.Gary.GaryRESTful.domain;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Transient; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert; @Entity
public class User implements UserDetails{ @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password; //用户是否没有失效
@Transient
private boolean accountNonExpried;
//用户是否冻结
@Transient
private boolean accountNonLocked;
//证明是否过期
@Transient
private boolean credentialsNonExpired;
//判断是否删除
@Transient
private boolean enabled;
@Transient
//添加 @Transient 注解可以不将 Set<GrantedAuthority>映射到数据库表上
private Set<GrantedAuthority> authorities; //给hibernatre用的构造方法
protected User() { } public User(Long id,String username,String password)
{
this.id = id;
this.username = username;
this.password = password;
} //给SpringSecurity用的构造方法
public User(String username,String password,
Collection<? extends GrantedAuthority> authorities) {
this(username,password,true,true,true,true,authorities);
} public User(String username, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) { if (((username == null) || "".equals(username)) || (password == null)) {
throw new IllegalArgumentException(
"Cannot pass null or empty values to constructor");
} this.username = username;
this.password = password;
this.enabled = enabled;
this.accountNonExpried = accountNonExpired;
this.credentialsNonExpired = credentialsNonExpired;
this.accountNonLocked = accountNonLocked;
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
} private static SortedSet<GrantedAuthority> sortAuthorities(
Collection<? extends GrantedAuthority> authorities) {
Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
// Ensure array iteration order is predictable (as per
// UserDetails.getAuthorities() contract and SEC-717)
SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<>(
new AuthorityComparator()); for (GrantedAuthority grantedAuthority : authorities) {
Assert.notNull(grantedAuthority,
"GrantedAuthority list cannot contain any null elements");
sortedAuthorities.add(grantedAuthority);
} return sortedAuthorities;
} private static class AuthorityComparator implements Comparator<GrantedAuthority>,
Serializable {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; public int compare(GrantedAuthority g1, GrantedAuthority g2) {
// Neither should ever be null as each entry is checked before adding it to
// the set.
// If the authority is null, it is a custom authority and should precede
// others.
if (g2.getAuthority() == null) {
return -1;
} if (g1.getAuthority() == null) {
return 1;
} return g1.getAuthority().compareTo(g2.getAuthority());
}
} public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
} //用户权限
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return authorities;
} //用户是否没有失效
@Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return accountNonExpried;
} //用户是否被冻结
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return accountNonLocked;
} //用户是否证明权限过期
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return credentialsNonExpired;
} //判断用户是否删除
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return enabled;
} }

User.java

  完善User.java实体

    public User(Long id,String username,String password)
{
this.id = id;
this.username = username;
this.password = password;
} //给SpringSecurity用的构造方法
public User(String username,String password,
Collection<? extends GrantedAuthority> authorities) {
this(username,password,true,true,true,true,authorities);
} public User(String username, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) { if (((username == null) || "".equals(username)) || (password == null)) {
throw new IllegalArgumentException(
"Cannot pass null or empty values to constructor");
} this.username = username;
this.password = password;
this.enabled = enabled;
this.accountNonExpried = accountNonExpired;
this.credentialsNonExpired = credentialsNonExpired;
this.accountNonLocked = accountNonLocked;
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
} private static SortedSet<GrantedAuthority> sortAuthorities(
Collection<? extends GrantedAuthority> authorities) {
Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
// Ensure array iteration order is predictable (as per
// UserDetails.getAuthorities() contract and SEC-717)
SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<>(
new AuthorityComparator()); for (GrantedAuthority grantedAuthority : authorities) {
Assert.notNull(grantedAuthority,
"GrantedAuthority list cannot contain any null elements");
sortedAuthorities.add(grantedAuthority);
} return sortedAuthorities;
} private static class AuthorityComparator implements Comparator<GrantedAuthority>,
Serializable {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; public int compare(GrantedAuthority g1, GrantedAuthority g2) {
// Neither should ever be null as each entry is checked before adding it to
// the set.
// If the authority is null, it is a custom authority and should precede
// others.
if (g2.getAuthority() == null) {
return -1;
} if (g1.getAuthority() == null) {
return 1;
} return g1.getAuthority().compareTo(g2.getAuthority());
}
}
package com.Gary.GaryRESTful.domain;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert; @Entity
public class User implements UserDetails{ @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password; //用户是否没有失效
private boolean accountNonExpried;
//用户是否冻结
private boolean accountNonLocked;
//证明是否过期
private boolean credentialsNonExpired;
//判断是否删除
private boolean enabled;
private Set<GrantedAuthority> authorities; //给hibernatre用的构造方法
protected User() { } public User(Long id,String username,String password)
{
this.id = id;
this.username = username;
this.password = password;
} //给SpringSecurity用的构造方法
public User(String username,String password,
Collection<? extends GrantedAuthority> authorities) {
this(username,password,true,true,true,true,authorities);
} public User(String username, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) { if (((username == null) || "".equals(username)) || (password == null)) {
throw new IllegalArgumentException(
"Cannot pass null or empty values to constructor");
} this.username = username;
this.password = password;
this.enabled = enabled;
this.accountNonExpried = accountNonExpired;
this.credentialsNonExpired = credentialsNonExpired;
this.accountNonLocked = accountNonLocked;
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
} private static SortedSet<GrantedAuthority> sortAuthorities(
Collection<? extends GrantedAuthority> authorities) {
Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
// Ensure array iteration order is predictable (as per
// UserDetails.getAuthorities() contract and SEC-717)
SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<>(
new AuthorityComparator()); for (GrantedAuthority grantedAuthority : authorities) {
Assert.notNull(grantedAuthority,
"GrantedAuthority list cannot contain any null elements");
sortedAuthorities.add(grantedAuthority);
} return sortedAuthorities;
} private static class AuthorityComparator implements Comparator<GrantedAuthority>,
Serializable {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; public int compare(GrantedAuthority g1, GrantedAuthority g2) {
// Neither should ever be null as each entry is checked before adding it to
// the set.
// If the authority is null, it is a custom authority and should precede
// others.
if (g2.getAuthority() == null) {
return -1;
} if (g1.getAuthority() == null) {
return 1;
} return g1.getAuthority().compareTo(g2.getAuthority());
}
} public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
} //用户权限
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return authorities;
} //用户是否没有失效
@Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return accountNonExpried;
} //用户是否被冻结
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return accountNonLocked;
} //用户是否证明权限过期
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return credentialsNonExpired;
} //判断用户是否删除
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return enabled;
} }

User.java

  完善UserRepository.java接口,实现查找用户姓名方法

    @Query(value = "select * from user where username = ?1",nativeQuery = true)
User findUserByUsername(String username);

  在UserService.java中实现查找用户Service

    @Autowired
private PasswordEncoder passwordEncoder; @Autowired
private UserRepository userRepository; //spring security默认处理登陆(username为输入的username)
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO Auto-generated method stub
//System.out.println(username);
User user = userRepository.findUserByUsername(username);
//用户名,密码,权限
//User实现UserDetails接口
return new User(username,passwordEncoder.encode(user.getPassword()),AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}

  测试时发现,当用户输入错误的用户名和密码时,控制台会报空指针异常,前台为给出“坏的凭证”给用户提示信息。

  原因:springsecurity会拦截一切其它的请求。只有当用户输入正确的用户名和密码,springsecurity才会释放用户正常的请求。

package com.Gary.GaryRESTful.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; //Web应用安全适配器
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{ //告诉SpringSecurity密码用什么加密的
@Bean
public PasswordEncoder passwordEncoder()
{
return new BCryptPasswordEncoder();
} //表单验证(身份认证)
protected void configure(HttpSecurity http) throws Exception{
http.formLogin()
.and()
//请求授权
.authorizeRequests()
//所有请求都被拦截,跳转到(/login请求中)
.anyRequest()
//都需要我们身份认证
.authenticated();
} }

SecurityConfig.java

package com.Gary.GaryRESTful.repository;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository; import com.Gary.GaryRESTful.domain.User; public interface UserRepository extends CrudRepository<User,Long>{ @Query(value = "select * from user where username = ?1",nativeQuery = true)
User findUserByUsername(String username); }

UserRepository.java

package com.Gary.GaryRESTful.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; import com.Gary.GaryRESTful.domain.User;
import com.Gary.GaryRESTful.repository.UserRepository; //用SprinSecurity默认的登陆系统
//UserService要实现UserDetailsService接口
@Component
public class UserService implements UserDetailsService{ @Autowired
private PasswordEncoder passwordEncoder; @Autowired
private UserRepository userRepository; //spring security默认处理登陆(username为输入的username)
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO Auto-generated method stub
//System.out.println(username);
User user = userRepository.findUserByUsername(username);
//用户名,密码,权限
//User实现UserDetails接口
return new User(username,passwordEncoder.encode(user.getPassword()),AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
} }

UserService.java

  所以我们可以在UserDetails.java中进行修改,添加判断,如果在数据库中未查询到用户时返回null

  @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO Auto-generated method stub
//System.out.println(username);
User user = userRepository.findUserByUsername(username);
//用户名,密码,权限
if(user == null)
{
throw new UsernameNotFoundException(username);
}
//User实现UserDetails接口
return new User(username,passwordEncoder.encode(user.getPassword()),AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}

package com.Gary.GaryRESTful.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; import com.Gary.GaryRESTful.domain.User;
import com.Gary.GaryRESTful.repository.UserRepository; //用SprinSecurity默认的登陆系统
//UserService要实现UserDetailsService接口
@Component
public class UserService implements UserDetailsService{ @Autowired
private PasswordEncoder passwordEncoder; @Autowired
private UserRepository userRepository; //spring security默认处理登陆(username为输入的username)
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO Auto-generated method stub
//System.out.println(username);
User user = userRepository.findUserByUsername(username);
//用户名,密码,权限
if(user == null)
{
throw new UsernameNotFoundException(username);
}
//User实现UserDetails接口
return new User(username,passwordEncoder.encode(user.getPassword()),AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
} }

UserService.java

  拓展:根据SpringSecurity提供的User方法

    //给SpringSecurity用的构造方法
public User(String username,String password,
Collection<? extends GrantedAuthority> authorities) {
this(username,password,true,true,true,true,authorities);
}

  可以在UserService.java中提供的UserDetails返回值中添加4个boolean值

return new User(user.getUsername(),passwordEncoder.encode(user.getPassword()),true,true,true,true,AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));

  这四个boolean值代表着

        //用户是否没有失效
@Transient
private boolean accountNonExpried;
//用户是否冻结
@Transient
private boolean accountNonLocked;
//证明是否过期
@Transient
private boolean credentialsNonExpired;
//判断是否删除
@Transient
private boolean enabled;

  如果return返回值中四个参数都为true,springscurity不会去进行拦截验证,

  当其中一个参数为false时,springsecurity就会对用户进行拦截验证~

  

JavaWeb-SpringSecurity在数据库中查询登陆用户的更多相关文章

  1. flask再学习-思考之怎么从数据库中查询数据在页面展示!

    看别人视频觉得很简单,要自己做蒙蔽了!这样子.NO! 1. 流程: 首先要有和数据库连接的驱动!一般有PYMySQL mysqlclient 等 使用扩展Flask-SQLAlchemy 获得orm对 ...

  2. JDBC方式从数据库中查询数据并显示

    1.创建数据库表myuser DROP TABLE IF EXISTS `myuser`; CREATE TABLE `myuser` ( `) NOT NULL COMMENT '姓名', `id` ...

  3. SQL Server数据库中还原孤立用户的方法集合

    虽然SQL Server现在搬迁的技术越来越多,自带的方法也越来越高级. 但是我们的SQL Server在搬迁的会出现很多孤立用户,微软没有自动的处理. 因为我们的数据库权限表都不会在应用数据库中,但 ...

  4. SQLServer: 解决“错误15023:当前数据库中已存在用户或角色

    解决SQL Server 2008 错误15023:当前数据库中已存在用户或角色,SQLServer2008,错误15023, 在使用SQL Server 2008时,我们经常会遇到一个情况:需要把一 ...

  5. SQL Server 2008 错误15023:当前数据库中已存在用户或角色

    解决SQL Server 2008 错误15023:当前数据库中已存在用户或角色,SQLServer2008,错误15023,在使用SQL Server 2008时,我们经常会遇到一个情况:需要把一台 ...

  6. 从Oracle数据库中查询前几个月数据时需要注意的一些问题

    在最近的一个项目中,有一个需求就是要查询数据库中前几个月的历史数据,但是由于自己考虑不全面造成了程序的bug,现在将这一块好好作一个总结,希望以后不再犯这种很低级的错误,首先贴出查询中用到的一个子函数 ...

  7. 在mysql数据库中创建Oracle数据库中的scott用户表

    在mysql数据库中创建Oracle数据库中的scott用户表 作者:Eric 微信:loveoracle11g create table DEPT ( DEPTNO int(2) not null, ...

  8. MongoDB数据库中查询数据(下)

    MongoDB数据库中查询数据(下) 在find中,options参数值为一个对象,用来设置查询数据时使用的选项,下面我们来对该参数值对象中可以使用的属性进行介绍: 1. fields; 该属性值为一 ...

  9. 在MongoDB数据库中查询数据(上)

    在MongoDB数据库中查询数据(上) 在MongoDB数据库中,可以使用Collection对象的find方法从一个集合中查询多个数据文档,find方法使用方法如下所示: collection.fi ...

随机推荐

  1. react的嵌套组件

    react没有vue插槽的概念,但是有嵌套组件,可以用嵌套组件实现类似插槽的功能.下例中,color,name,btn相当于具名插槽,children相当于匿名插槽. import React fro ...

  2. Lab 色彩模型和取值范围

    L∈(0,100) a∈(-128,127) b∈(-128,127) opencv 的Lab数据对齐做了量化,使其处于0-255范围 L=L*2.55 a=a+128 b=b+128

  3. 基于光线追踪的渲染中景深(Depth of field)效果的实现

    图形学离线渲染中常用的透视摄像机模型时根据小孔成像的原理建立的,其实现通常是从向成像平面上发射ray,并把trace这条ray的结果作为成像平面上对应交点的采样结果.即: 图片来自<Fundam ...

  4. http请求204

    项目中发现一个奇怪的问题,请求的时候同一个接口有两个请求,而且有一个状态为204,有一个为200 在网上查看资料后得知,是因为跨域而引起的,OPTIONS是一种“预检请求”,浏览器在处理跨域访问的请求 ...

  5. httpclient 上传附件实例

    httpclient 单附件上传实例  (扩展多附件上传实例,点我) /** * 上传附件 * @param host * @param uri * @param filePath 文件路径 * @p ...

  6. Python中GUI库PyQt5的安装和配置

    在使用Tkinter开发GUI程序时,发现相关文档比较少,开发起来太累.经过综合比较,决定使用PyQt这个库.下面是简单的安装步骤. 1.安装 PyQt5 : pip install PyQt5 -i ...

  7. ASE19 团队项目 模型组 scrum report集合

    scrum report 链接 scrum1 report scrum2 report scrum3 report scrum4 report scrum5 report scrum6 report ...

  8. 【死磕 Java 集合】— ConcurrentSkipListMap源码分析

    转自:http://cmsblogs.com/?p=4773 [隐藏目录] 前情提要 简介 存储结构 源码分析 主要内部类 构造方法 添加元素 添加元素举例 删除元素 删除元素举例 查找元素 查找元素 ...

  9. SQL语句复习【专题二】

    SQL语句复习[专题二] 单行函数(日期.数学.字符串.通用函数.转换函数)多行函数.分组函数.多行数据计算一个结果.一共5个.sum(),avg(),max(),min(),count()分组函数  ...

  10. 将本地代码使用Git上传更新至Github

    注册.配置git 1. 首先注册git image 2.然后下载.配置git 百度“git下载”,然后默认安装,注意的是最后要添加环境变量,最后安装结果如下: image 配置如下: 1.设置本地的s ...