栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot组件速查

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot组件速查

使用须知
本速搭为作者经验所成,若有问题请联系修改
该速搭不适用于新手,建议收藏,未来掌握springboot后可以使用

pom.xml配置

pom.xml启动器
    
        
        
            org.springframework.boot
            spring-boot-starter
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
        
            org.springframework.boot
            spring-boot-devtools
            true
        
        
        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        
        
        
            mysql
            mysql-connector-java
            runtime
        
        
        
            org.projectlombok
            lombok
            true
        
        
        
            junit
            junit
        
        
        
            org.springframework.boot
            spring-boot-starter-validation
        
    


pom.xml构建排除项
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                
            
        
    

yml设置
# *** 解除注释为选则使用 ***
spring:
  # 设置数据库
  datasource:
    # *** 根据mysql版本调整 ***
    driver-class-name: com.mysql.cj.jdbc.Driver
    # *** 【必填】修改数据库(xgk2023) ***
    url: jdbc:mysql://localhost:3306/Name?serverTimezone=GMT%2B8
    # *** 【必填】修改用户名账号密码 ***
    username: root
    password: 123456
  thymeleaf:
    cache: false

  # ***【选填】使templates里的html能访问到static里的静态资源 ***
  # templates里的html访问不到static里的静态资源时添加 
#  mvc:
#    static-path-pattern: /static
        boolean serviceNameStartWithI = false;//user -> UserService 设置成true: user -> IUserService
        generateByTables(serviceNameStartWithI, packageName, "user"); 
    }

    private void generateByTables(boolean serviceNameStartWithI, String packageName, String... tableNames) {
        GlobalConfig config = new GlobalConfig();
        String dbUrl = "jdbc:mysql://localhost:3306/xgk2023";       
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL)
                .setUrl(dbUrl)
                .setUsername("root")    
                .setPassword("123456")  
                .setDriverName("com.mysql.jdbc.Driver");
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig
                .setCapitalMode(true)
                .setEntityLombokModel(true) // 实体是否为lombok模型(默认 false)
                .setNaming(NamingStrategy.underline_to_camel)	// 命名法转换
                .setInclude(tableNames);
        config.setActiveRecord(false)
                .setAuthor("hlt")
                .setOutputDir("D://Projects//IDEA//springboot-01-helloworld//src//main//java") 
                .setFileOverride(true);
        if (!serviceNameStartWithI) {
            config.setServiceName("%sService");
        }
        new AutoGenerator().setGlobalConfig(config)
                .setDataSource(dataSourceConfig)
                .setStrategy(strategyConfig)
                .setPackageInfo(
                        new PackageConfig()		
                                .setParent(packageName)
                                .setController("controller")
                                .setEntity("entity")
                ).execute();
    }

    private void generateByTables(String packageName, String... tableNames) {
        generateByTables(true, packageName, tableNames);
    }
}

分页组件
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@MapperScan("com.sdjzu.xgk.mapper")
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
    
    
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
    
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInterceptor.setLimit(500);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
}


分页组件使用方法
Page page = new Page<>(current, 10);	
// 第一个参数 页码   第二个参数  每页数量
xgkMapper.selectPage(page, null);
// 第一个参数 分页器   第二个参数  查询条件
List xgks = page.getRecords();

实体与数据库关系绑定设置的注解
// 设置实体类对应的表名
@TableName("表名")

// 将属性对应的字段指定为主键
// value 用于指定主键的字段
// type 设置主键生成策略  默认雪花算法 案例中使用的自增
@TableId(value="字段名",type="IdType.AUTO")		

// 指定属性所对应的字段名
@TableField("字段名")

// 指定属性对应的字段为逻辑删除字段
@TableLogic

SpringSecurity安全

注意:
  1. Security配置中未定义的组件可先注释掉,不影响正常使用。
  2. Security配置中需要的组件在本文章中都能找到
引入依赖


  org.springframework.boot
  spring-boot-starter-security

数据库时区设置
url: jdbc:mysql://localhost:3306/xgk2023?serverTimezone=GMT%2B8
# ?serverTimezone=GMT%2B8 注意添加这一部分

Security配置组件
import com.sdjzu.xgk.security.*;
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.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    LoginFailureHandler loginFailureHandler; 	

    @Autowired
    LoginSuccessHandler loginSuccessHandler;	

    @Autowired
    CaptchaFilter captchaFilter;	

    @Autowired
    JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; 

    @Autowired
    JwtAccessDeniedHandler jwtAccessDeniedHandler;	

    @Autowired
    UserDetailServiceImpl userDetailService;	
    
        private static final String[] URL_WHITELIST = {
            
            //  "
                .failureHandler(loginFailureHandler) 
                .loginPage("/xxx")          		 
                .loginProcessingUrl("/login")   	 
                .defaultSuccessUrl("/xxx")   		 
                .permitAll()
            // 注销配置
                .and()			// .and() 相当于 http
                .logout()
                .logoutUrl("/logout")  		
                .logoutSuccessUrl("/xxx") 	
                .permitAll();
            // 禁用session
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            // 配置拦截规则
                .and()
                .authorizeRequests()
                .antMatchers(URL_WHITELIST).permitAll()
                .anyRequest().authenticated()	// 允许任何请求类型
                
            // 配置异常处理器
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .accessDeniedHandler(jwtAccessDeniedHandler)
            // 配置过滤器
                .and()
                .addFilter(jwtAuthenticationFilter())	// 添加jwt身份验证过滤器
                // 在用户名密码认证过滤器前添加验证码过滤器
                .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)
                
    }
    
    // 配置自定义的登录验证器
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailService);
    }
}


登录处理组件
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sdjzu.xgk.entity.Users;
import com.sdjzu.xgk.mapper.UsersMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
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.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserDetailServiceImpl implements UserDetailsService {

	@Autowired
	UsersMapper usersMapper;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

		QueryWrapper wrapper = new QueryWrapper<>();
		wrapper.eq("username", username);
		Users user = usersMapper.selectOne(wrapper);
		if (user == null) {
			throw new UsernameNotFoundException("用户名或密码不正确");
		}
		List auths = AuthorityUtils
				.commaSeparatedStringToAuthorityList(
						
						user.getRoot() + "," + user.getRole()
				);
		return new User(
				user.getUsername(),  // 账号
				new BCryptPasswordEncoder().encode(user.getPassword()), // 密码
				auths  // 传入的角色  固定
		);
	}

	public List getUserAuthority(String username){
		QueryWrapper wrapper = new QueryWrapper<>();
		wrapper.eq("username", username);
		Users user = usersMapper.selectOne(wrapper);
		if (user == null) {
			throw new UsernameNotFoundException("用户名或密码不正确");
		}
		return AuthorityUtils
				.commaSeparatedStringToAuthorityList(
						user.getRoot() + "," + user.getRole()
				);
	}

}

登录失败处理组件
import cn.hutool.json.JSONUtil;

import com.sdjzu.xgk.common.lang.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {

	@Override
	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {

		response.setContentType("application/json;charset=UTF-8");
		ServletOutputStream outputStream = response.getOutputStream();

		Result result = Result.fail("用户名或密码错误");
        result.setMsg(exception.getMessage());
        result.setCode(201);
		outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));

		outputStream.flush();
		outputStream.close();
	}
}

登录成功处理组件
import cn.hutool.json.JSONUtil;
import com.sdjzu.xgk.common.lang.Result;
import com.sdjzu.xgk.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler {

	@Autowired
	JwtUtils jwtUtils;

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
		// 获取当前响应信息
        response.setContentType("application/json;charset=UTF-8");
		ServletOutputStream outputStream = response.getOutputStream();

		// 生成jwt,并添加到响应头中
		String jwt = jwtUtils.generateToken(authentication.getName());
		response.setHeader(jwtUtils.getHeader(), jwt);
        
        // 生成Result,并添加到响应中
		Result result = Result.succ("");
		outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));

		outputStream.flush();
		outputStream.close();
	}

}

通过注解设置权限
在接口或接口类前添加如下注解
用户具有某个角色,可以访问方法
@Secured({"ROLE_sale","ROLE_manager"}) 
使用于进入方法前的权限验证
可以将登录用户的roles/premissions参数传入到方法中
@PreAuthorize("hasRole('ROLE_管理员')")
@PreAuthorize("hasAnyAuthority('menu:system')")
使用于进入方法后的权限验证  常用于返回值
@PostAuthorize("hasAnyAuthority('menu:system')")
    以下两个注解用在上面几个注解之后
权限验证之后对数据进行过滤,留下用户名是admin1的数据
表达式中filterObject引用的方法是返回值List中的某一个元素
@PostFilter("filterObject.username == 'admin1'")
进入控制器之前对数据进行过滤
@PreFilter(value = "filterObject.id%2==0")

redis工具

引入依赖


  org.springframework.boot
  spring-boot-starter-data-redis

redis配置
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
    @Bean
    RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        jackson2JsonRedisSerializer.setObjectMapper(new ObjectMapper());

        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        return redisTemplate;
    }
}

redis工具类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {

    @Autowired
    private RedisTemplate redisTemplate;

    
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

    //============================String=============================

    
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }

    //================================Map=================================

    
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    
    public Map hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    
    public boolean hmset(String key, Map map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public boolean hmset(String key, Map map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }

    //============================set=============================

    
    public Set sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0) expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    
    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    //===============================list=================================

    
    public List lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public boolean lSet(String key, List value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public boolean lSet(String key, List value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    //================有序集合 sort set===================

    
    public boolean zSet(String key, Object value, double score) {
        return redisTemplate.opsForZSet().add(key, value, score);
    }

    public long batchZSet(String key, Set typles) {
        return redisTemplate.opsForZSet().add(key, typles);
    }

    public void zIncrementScore(String key, Object value, long delta) {
        redisTemplate.opsForZSet().incrementScore(key, value, delta);
    }

    public void zUnionAndStore(String key, Collection otherKeys, String destKey) {
        redisTemplate.opsForZSet().unionAndStore(key, otherKeys, destKey);
    }

    
    public long getZsetScore(String key, Object value) {
        Double score = redisTemplate.opsForZSet().score(key, value);
        if (score == null) {
            return 0;
        } else {
            return score.longValue();
        }
    }

    
    public Set getZSetRank(String key, long start, long end) {
        return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
    }

}
 

验证码验证

前置:需要redis工具

引入依赖


  com.github.axet
  kaptcha
  0.0.9

验证码异常处理组件
import org.springframework.security.core.AuthenticationException;

public class CaptchaException extends AuthenticationException {
    public CaptchaException(String msg) {
        super(msg);
    }
}

验证码过滤组件
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.sdjzu.xgk.common.exception.CaptchaException;
import com.sdjzu.xgk.common.lang.Const;
import com.sdjzu.xgk.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class CaptchaFilter extends OncePerRequestFilter {

	@Autowired
	RedisUtil redisUtil;	

	@Autowired
	LoginFailureHandler loginFailureHandler; 

	@Override
	protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {

		String url = httpServletRequest.getRequestURI();
        // 捕获地址为 /login 且方式为 post 的请求
		if ("/login".equals(url) && httpServletRequest.getMethod().equals("POST")) {
			try{
				// 校验验证码
				validate(httpServletRequest);
			} catch (CaptchaException e) {
				// 检验验证码失败-->交给认证失败处理器
				loginFailureHandler.onAuthenticationFailure(httpServletRequest, httpServletResponse, e);
			}
		}
        // 校验验证码成功-->交给下一个过滤器
		filterChain.doFilter(httpServletRequest, httpServletResponse);
	}

	// 校验验证码逻辑
	private void validate(HttpServletRequest httpServletRequest) {

		String code = httpServletRequest.getParameter("code"); 
		String key = httpServletRequest.getParameter("token"); 

		if (StringUtils.isBlank(code) || StringUtils.isBlank(key)) {
			throw new CaptchaException("验证码错误"); // 判断code/key 是否为空或含有空白字符
		}

		if (!code.equals(redisUtil.hget(Const.CAPTCHA_KEY, key))) {
			throw new CaptchaException("验证码错误"); // 判断redis里是否含有该验证码信息
		}
        
		// 一次性使用
		redisUtil.hdel(Const.CAPTCHA_KEY, key); // 删除本次识别验证码在redis对应的信息
	}
}

验证码样式配置
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

@Configuration
public class KaptchaConfig {
    @Bean
    public DefaultKaptcha producer() {
        Properties properties = new Properties();
        properties.put("kaptcha.border", "no"); // 是否有边框
        properties.put("kaptcha.textproducer.font.color", "black"); // 颜色
        properties.put("kaptcha.textproducer.char.space", "4"); // 每个字符的空行
        properties.put("kaptcha.image.height", "40");   // 高度
        properties.put("kaptcha.image.width", "120");   // 宽度
        properties.put("kaptcha.textproducer.font.size", "30"); // 文字大小

        Config config = new Config(properties);
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        defaultKaptcha.setConfig(config);

        return defaultKaptcha;
    }
}

验证码注入配置
import com.sdjzu.xgk.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;

public class BaseController {
    @Autowired
    HttpServletRequest req;

    @Autowired
    RedisUtil redisUtil;
}

验证码路由配置
import cn.hutool.core.lang.UUID;
import cn.hutool.core.map.MapUtil;
import com.google.code.kaptcha.Producer;
import com.sdjzu.xgk.common.lang.Const;
import com.sdjzu.xgk.common.lang.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

@CrossOrigin
@RestController
public class AuthController extends BaseController {

    @Autowired
    Producer producer;

    @GetMapping("/captcha")
    public Result captcha() throws IOException {
        String key = UUID.randomUUID().toString();
        String code = producer.createText();


        BufferedImage image = producer.createImage(code);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", outputStream);

        BASE64Encoder encoder = new BASE64Encoder();
        String str = "data:image/jpeg;base64,";

        String base64Img = str + encoder.encode(outputStream.toByteArray());

        redisUtil.hset(Const.CAPTCHA_KEY, key, code, 120);

        return Result.succ(
                MapUtil.builder()
                        .put("token", key)
                        .put("captchaImg", base64Img)
                        .build()
        );
    }
}

jwt配置

引入依赖


  io.jsonwebtoken
  jjwt
  0.9.1



  cn.hutool
  hutool-all
  5.3.3


  org.apache.commons
  commons-lang3
  3.11


  org.freemarker
  freemarker
  2.3.30

jwt身份验证过滤器
import cn.hutool.core.util.StrUtil;
import com.sdjzu.xgk.entity.Users;
import com.sdjzu.xgk.mapper.UsersMapper;
import com.sdjzu.xgk.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class JwtAuthenticationFilter extends BasicAuthenticationFilter {

    @Autowired
    JwtUtils jwtUtils;	
    
    @Autowired
    UsersMapper usersMapper;
    
    @Autowired
    UserDetailServiceImpl userDetailService;	
    
    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        String jwt = request.getHeader(jwtUtils.getHeader()); 
        if (StrUtil.isBlankOrUndefined(jwt)) {
            chain.doFilter(request, response);	// token为空-->进入下一层过滤器
            return;
        }

        Claims claim = jwtUtils.getClaimByToken(jwt);	// 解析token
        if (claim == null) {
            throw new JwtException("token 异常");		// 解析token失败
        }
        if (jwtUtils.isTokenExpired(claim)) {
            throw new JwtException("token已过期");		// 验证token时效
        }

        String username = claim.getSubject();		// 获取token所属用户名

        UsernamePasswordAuthenticationToken token	// 包装凭证
                = new UsernamePasswordAuthenticationToken(
                username,	// 用户名
                null,
                userDetailService.getUserAuthority(username)	// 权限
        );

        SecurityContextHolder.getContext().setAuthentication(token);	// 存入Security

        chain.doFilter(request, response);	// 进入下一层过滤器
    }
}

jwt认证入口点
import cn.hutool.json.JSONUtil;

import com.sdjzu.xgk.common.lang.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {

	@Override
	public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {

		response.setContentType("application/json;charset=UTF-8");	// 设置响应内容类型
		response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);	// 设置响应状态码
		ServletOutputStream outputStream = response.getOutputStream(); // 获取响应的输出流
        
        //生成result,并添加到响应中
		Result result = Result.fail("请先登录");
		outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));

		outputStream.flush(); // 将缓冲区所有的数据输出
		outputStream.close(); // 关闭缓冲区
	}
}

jwt拒绝访问处理组件
package com.sdjzu.xgk.security;

import cn.hutool.json.JSONUtil;

import com.sdjzu.xgk.common.lang.Result;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {

	@Override
	public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {

		response.setContentType("application/json;charset=UTF-8"); // 设置响应内容类型
		response.setStatus(HttpServletResponse.SC_FORBIDDEN);      // 设置响应状态码
		ServletOutputStream outputStream = response.getOutputStream(); // 获取响应的输出流
        
        //生成result,并添加到响应中
		Result result = Result.fail(accessDeniedException.getMessage());
		outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));

		outputStream.flush();	// 将缓冲区所有的数据输出
		outputStream.close();	// 关闭缓冲区

	}
}

yml添加变量
markerhub:
  jwt:
    header: Authorization
    expire: 604800 #7天,秒单位
    secret: ji8n3439n439n43ld9ne93kdusyxgshx

jwt工具类
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;

@Data
@Component
@ConfigurationProperties(prefix = "markerhub.jwt")
public class JwtUtils {

	private long expire;
	private String secret;
	private String header;

	// 生成jwt
	public String generateToken(String username) {

		Date nowDate = new Date();
		Date expireDate = new Date(nowDate.getTime() + 1000 * expire);

		return Jwts.builder()
				.setHeaderParam("typ", "JWT")
				.setSubject(username)
				.setIssuedAt(nowDate)
				.setExpiration(expireDate)// 7天過期
				.signWith(SignatureAlgorithm.HS512, secret)
				.compact();
	}

	// 解析jwt
	public Claims getClaimByToken(String jwt) {
		try {
			return Jwts.parser()
					.setSigningKey(secret)
					.parseClaimsJws(jwt)
					.getBody();
		} catch (Exception e) {
			return null;
		}
	}

	// jwt是否过期
	public boolean isTokenExpired(Claims claims) {
		return claims.getExpiration().before(new Date());
	}
    
    // 一个完整的token
    public String generateToken() {

		Date nowDate = new Date();
		Date expireDate = new Date(nowDate.getTime() + 1000 * 60 * 60 * 24);
        Date NotBefore = new Date(nowDate.getTime())

       return Jwts.builder()
                //设置头部
                .setHeaderParam("typ", "JWT")	//设置token的类型
                .setHeaderParam("alg", "HS256")	//声明token使用的签名算法
                //添加载荷
                .claim("xxx", "xxx")		// 添加自定义信息
                //设置主体 - 属于载荷
                .setIssuer("jwt")			// jwt签发者
                .setSubject("user")			// jwt所面向的用户
                .setAudience("username")		// 接收jwt的一方
                .setExpiration(expireDate)  // jwt的过期时间
                .setNotBefore()				// 定义在什么时间之前,该token都是不可用的
                .setIssuedAt(nowDate)		// jwt的签发时间
                .setId(UUID.randomUUID().toString())// jwt的唯一身份标识,避免重复
                //设置签证
                .signWith(SignatureAlgorithm.HS256, signature) // 使用算法编码
                .compact();					// 拼接签名
	}
}

EasyExcel使用

引入依赖


    com.alibaba
    easyexcel
    2.1.6

监听器配置
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.extension.service.IService;
import com.sdjzu.xgk.entity.Category;
import com.sdjzu.xgk.entity.Users;
import com.sdjzu.xgk.service.UsersService;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

// 有个很重要的点 ExcelListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class ExcelListener> extends AnalysisEventListener {

    private List list = new ArrayList<>();
    
    private static final int BATCH_COUNT = 5;

    
    private Service usersService;

    
    public ExcelListener(Service usersService) {
        this.usersService = usersService;
    }


    
    @Override
    public void invoke(Entity goods, AnalysisContext analysisContext) {
        System.out.println("解析到一条数据:========================" + goods.toString());
        // 数据存储到datas,供批量处理,或后续自己业务逻辑处理。
        list.add(goods);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理datas
            list.clear();
        }

    }

    
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        saveData();//确保所有数据都能入库
    }

    
    private void saveData() {
        System.out.println("==============================" + list.size() + "条数据,开始存储到数据库");
        usersService.saveBatch((Collection) list);
    }

}

工具类
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

public class ExcelUtil {
    public static void download(HttpServletResponse response, Class t, List list,String filename) throws IOException {
        response.setContentType("application/vnd.ms-excel");// 设置文本内省
        response.setCharacterEncoding("utf-8");// 设置字符编码
        response.setHeader("Content-disposition", "attachment;filename="+filename+".xlsx"); // 设置响应头
        EasyExcel.write(response.getOutputStream(), t).sheet("模板").doWrite(list); //用io流来写入数据
    }
    public static void upload( Class t, IService service, MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), t , new ExcelListener(service)).sheet().doRead();
    }
}

对操作的实体添加注解
@ExcelIgnore   // 该属性不会被导出
@ExcelProperty("权限")  // 该属性的表头

使用方法
    //导出为Excel
    @RequestMapping("/downloadexcel.do")
    public void download(HttpServletResponse response) throws IOException {
        List list = usersMapper.selectList(null);
        ExcelUtil.download(response,Users.class,list,"test"); // 最后一个参数为导出文件名
    }

    //导入Excel
    @RequestMapping("/importexcel.do")
    public void upload(@RequestParam(value = "excelFile") MultipartFile file) throws IOException{
        ExcelUtil.upload(Users.class,usersService,file);
    }
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号