Spring Boot整合Spring Security简单实现登入登出从零搭建教程

前言

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

本文主要给大家介绍了关于Spring Boot整合Spring Security实现登入登出的相关内容,下面话不多说了,来一起看看详细的介绍吧

技术栈 : SpringBoot + SpringSecurity + jpa + freemark ,完整项目地址 : https://github.com/EalenXie/spring-security-login  (本地下载)

方法如下:

1 . 新建一个spring-security-login的maven项目 ,pom.xml添加基本依赖 :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>com.wuxicloud</groupId>
 <artifactId>spring-security-login</artifactId>
 <version>1.0</version>
 <parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>1.5.6.RELEASE</version>
 </parent>
 <properties>
 <author>EalenXie</author>
 <description>SpringBoot整合SpringSecurity实现简单登入登出</description>
 </properties>

 <dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-jpa</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-security</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-freemarker</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-aop</artifactId>
 </dependency>
 <!--alibaba-->
 <dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>druid</artifactId>
 <version>1.0.24</version>
 </dependency>
 <dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>fastjson</artifactId>
 <version>1.2.31</version>
 </dependency>
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <scope>runtime</scope>
 </dependency>
 </dependencies>
</project>

2 . 准备你的数据库,设计表结构,要用户使用登入登出,新建用户表。

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `user_uuid` varchar(70) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
 `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
 `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
 `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
 `telephone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
 `role` int(10) DEFAULT NULL,
 `image` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
 `last_ip` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
 `last_time` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
 PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

3 . 用户对象User.java :

import javax.persistence.*;

/**
 * Created by EalenXie on 2018/7/5 15:17
 */
@Entity
@Table(name = "USER")
public class User {
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Integer id;
 private String user_uuid; //用户UUID
 private String username; //用户名
 private String password; //用户密码
 private String email; //用户邮箱
 private String telephone; //电话号码
 private String role; //用户角色
 private String image; //用户头像
 private String last_ip; //上次登录IP
 private String last_time; //上次登录时间

 public Integer getId() {
 return id;
 }

 public String getRole() {
 return role;
 }

 public void setRole(String role) {
 this.role = role;
 }

 public String getImage() {
 return image;
 }

 public void setImage(String image) {
 this.image = image;
 }

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

 public String getUsername() {
 return username;
 }

 public void setUsername(String username) {
 this.username = username;
 }

 public String getEmail() {
 return email;
 }

 public void setEmail(String email) {
 this.email = email;
 }

 public String getTelephone() {
 return telephone;
 }

 public void setTelephone(String telephone) {
 this.telephone = telephone;
 }

 public String getPassword() {
 return password;
 }

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

 public String getUser_uuid() {
 return user_uuid;
 }

 public void setUser_uuid(String user_uuid) {
 this.user_uuid = user_uuid;
 }

 public String getLast_ip() {
 return last_ip;
 }

 public void setLast_ip(String last_ip) {
 this.last_ip = last_ip;
 }

 public String getLast_time() {
 return last_time;
 }

 public void setLast_time(String last_time) {
 this.last_time = last_time;
 }

 @Override
 public String toString() {
 return "User{" +
 "id=" + id +
 ", user_uuid='" + user_uuid + '\'' +
 ", username='" + username + '\'' +
 ", password='" + password + '\'' +
 ", email='" + email + '\'' +
 ", telephone='" + telephone + '\'' +
 ", role='" + role + '\'' +
 ", image='" + image + '\'' +
 ", last_ip='" + last_ip + '\'' +
 ", last_time='" + last_time + '\'' +
 '}';
 }
}

4 . application.yml配置一些基本属性

spring:
 resources:
 static-locations: classpath:/
 freemarker:
 template-loader-path: classpath:/templates/
 suffix: .html
 content-type: text/html
 charset: UTF-8
 datasource:
 url: jdbc:mysql://localhost:3306/yourdatabase
 username: yourname
 password: yourpass
 driver-class-name: com.mysql.jdbc.Driver
 type: com.alibaba.druid.pool.DruidDataSource
server:
 port: 8083
 error:
 whitelabel:
 enabled: true

5 . 考虑我们应用的效率 , 可以配置数据源和线程池 :

package com.wuxicloud.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.*;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

@Configuration
public class DruidConfig {
 private static final String DB_PREFIX = "spring.datasource.";

 @Autowired
 private Environment environment;

 @Bean
 @ConfigurationProperties(prefix = DB_PREFIX)
 public DataSource druidDataSource() {
 Properties dbProperties = new Properties();
 Map<String, Object> map = new HashMap<>();
 for (PropertySource<?> propertySource : ((AbstractEnvironment) environment).getPropertySources()) {
 getPropertiesFromSource(propertySource, map);
 }
 dbProperties.putAll(map);
 DruidDataSource dds;
 try {
 dds = (DruidDataSource) DruidDataSourceFactory.createDataSource(dbProperties);
 dds.init();
 } catch (Exception e) {
 throw new RuntimeException("load datasource error, dbProperties is :" + dbProperties, e);
 }
 return dds;
 }

 private void getPropertiesFromSource(PropertySource<?> propertySource, Map<String, Object> map) {
 if (propertySource instanceof MapPropertySource) {
 for (String key : ((MapPropertySource) propertySource).getPropertyNames()) {
 if (key.startsWith(DB_PREFIX))
  map.put(key.replaceFirst(DB_PREFIX, ""), propertySource.getProperty(key));
 else if (key.startsWith(DB_PREFIX))
  map.put(key.replaceFirst(DB_PREFIX, ""), propertySource.getProperty(key));
 }
 }

 if (propertySource instanceof CompositePropertySource) {
 for (PropertySource<?> s : ((CompositePropertySource) propertySource).getPropertySources()) {
 getPropertiesFromSource(s, map);
 }
 }
 }

 @Bean
 public ServletRegistrationBean druidServlet() {
 return new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
 }

 @Bean
 public FilterRegistrationBean filterRegistrationBean() {
 FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
 filterRegistrationBean.setFilter(new WebStatFilter());
 filterRegistrationBean.addUrlPatterns("/*");
 filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
 return filterRegistrationBean;
 }
}

配置线程池 :

package com.wuxicloud.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableAsync
public class ThreadPoolConfig {
 @Bean
 public Executor getExecutor() {
 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
 executor.setCorePoolSize(5);//线程池维护线程的最少数量
 executor.setMaxPoolSize(30);//线程池维护线程的最大数量
 executor.setQueueCapacity(8); //缓存队列
 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //对拒绝task的处理策略
 executor.setKeepAliveSeconds(60);//允许的空闲时间
 executor.initialize();
 return executor;
 }
}

6.用户需要根据用户名进行登录,访问数据库 :

import com.wuxicloud.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * Created by EalenXie on 2018/7/11 14:23
 */
public interface UserRepository extends JpaRepository<User, Integer> {

 User findByUsername(String username);

}

7.构建真正用于SpringSecurity登录的安全用户(UserDetails),我这里使用新建了一个POJO来实现 :

package com.wuxicloud.security;

import com.wuxicloud.model.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;

public class SecurityUser extends User implements UserDetails {
 private static final long serialVersionUID = 1L;

 public SecurityUser(User user) {
 if (user != null) {
 this.setUser_uuid(user.getUser_uuid());
 this.setUsername(user.getUsername());
 this.setPassword(user.getPassword());
 this.setEmail(user.getEmail());
 this.setTelephone(user.getTelephone());
 this.setRole(user.getRole());
 this.setImage(user.getImage());
 this.setLast_ip(user.getLast_ip());
 this.setLast_time(user.getLast_time());
 }
 }

 @Override
 public Collection<? extends GrantedAuthority> getAuthorities() {
 Collection<GrantedAuthority> authorities = new ArrayList<>();
 String username = this.getUsername();
 if (username != null) {
 SimpleGrantedAuthority authority = new SimpleGrantedAuthority(username);
 authorities.add(authority);
 }
 return authorities;
 }

 @Override
 public boolean isAccountNonExpired() {
 return true;
 }

 @Override
 public boolean isAccountNonLocked() {
 return true;
 }

 @Override
 public boolean isCredentialsNonExpired() {
 return true;
 }

 @Override
 public boolean isEnabled() {
 return true;
 }
}

8 . 核心配置,配置SpringSecurity访问策略,包括登录处理,登出处理,资源访问,密码基本加密。

package com.wuxicloud.config;

import com.wuxicloud.dao.UserRepository;
import com.wuxicloud.model.User;
import com.wuxicloud.security.SecurityUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
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.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

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

/**
 * Created by EalenXie on 2018/1/11.
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);

 @Override
 protected void configure(HttpSecurity http) throws Exception { //配置策略
 http.csrf().disable();
 http.authorizeRequests().
 antMatchers("/static/**").permitAll().anyRequest().authenticated().
 and().formLogin().loginPage("/login").permitAll().successHandler(loginSuccessHandler()).
 and().logout().permitAll().invalidateHttpSession(true).
 deleteCookies("JSESSIONID").logoutSuccessHandler(logoutSuccessHandler()).
 and().sessionManagement().maximumSessions(10).expiredUrl("/login");
 }

 @Autowired
 public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
 auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
 auth.eraseCredentials(false);
 }

 @Bean
 public BCryptPasswordEncoder passwordEncoder() { //密码加密
 return new BCryptPasswordEncoder(4);
 }

 @Bean
 public LogoutSuccessHandler logoutSuccessHandler() { //登出处理
 return new LogoutSuccessHandler() {
 @Override
 public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
 try {
  SecurityUser user = (SecurityUser) authentication.getPrincipal();
  logger.info("USER : " + user.getUsername() + " LOGOUT SUCCESS ! ");
 } catch (Exception e) {
  logger.info("LOGOUT EXCEPTION , e : " + e.getMessage());
 }
 httpServletResponse.sendRedirect("/login");
 }
 };
 }

 @Bean
 public SavedRequestAwareAuthenticationSuccessHandler loginSuccessHandler() { //登入处理
 return new SavedRequestAwareAuthenticationSuccessHandler() {
 @Override
 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
 User userDetails = (User) authentication.getPrincipal();
 logger.info("USER : " + userDetails.getUsername() + " LOGIN SUCCESS ! ");
 super.onAuthenticationSuccess(request, response, authentication);
 }
 };
 }
 @Bean
 public UserDetailsService userDetailsService() { //用户登录实现
 return new UserDetailsService() {
 @Autowired
 private UserRepository userRepository;

 @Override
 public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
 User user = userRepository.findByUsername(s);
 if (user == null) throw new UsernameNotFoundException("Username " + s + " not found");
 return new SecurityUser(user);
 }
 };
 }
}

9.至此,已经基本将配置搭建好了,从上面核心可以看出,配置的登录页的url 为/login,可以创建基本的Controller来验证登录了。

package com.wuxicloud.web;

import com.wuxicloud.model.User;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * Created by EalenXie on 2018/1/11.
 */
@Controller
public class LoginController {

 @RequestMapping(value = "/login", method = RequestMethod.GET)
 public String login() {
 return "login";
 }

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

 public User getUser() { //为了session从获取用户信息,可以配置如下
 User user = new User();
 SecurityContext ctx = SecurityContextHolder.getContext();
 Authentication auth = ctx.getAuthentication();
 if (auth.getPrincipal() instanceof UserDetails) user = (User) auth.getPrincipal();
 return user;
 }

 public HttpServletRequest getRequest() {
 return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
 }
}

11 . SpringBoot基本的启动类 Application.class

package com.wuxicloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Created by EalenXie on 2018/7/11 15:01
 */
@SpringBootApplication
public class Application {

 public static void main(String[] args) {
 SpringApplication.run(Application.class, args);
 }
}

11.根据Freemark和Controller里面可看出配置的视图为 /templates/index.html和/templates/index.login。所以创建基本的登录页面和登录成功页面。

login.html

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>用户登录</title>
</head>
<body>
<form action="/login" method="post">
 用户名 : <input type="text" name="username"/>
 密码 : <input type="password" name="password"/>
 <input type="submit" value="登录">
</form>
</body>
</html>

注意 : 这里方法必须是POST,因为GET在controller被重写了,用户名的name属性必须是username,密码的name属性必须是password

index.html

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>首页</title>
 <#assign user=Session.SPRING_SECURITY_CONTEXT.authentication.principal/>
</head>
<body>
欢迎你,${user.username}<br/>
<a href="/logout">注销</a>
</body>
</html>

注意 : 为了从session中获取到登录的用户信息,根据配置SpringSecurity的用户信息会放在Session.SPRING_SECURITY_CONTEXT.authentication.principal里面,根据FreeMarker模板引擎的特点,可以通过这种方式进行获取 : <#assign user=Session.SPRING_SECURITY_CONTEXT.authentication.principal/>

12 . 为了方便测试,我们在数据库中插入一条记录,注意,从WebSecurity.java配置可以知道密码会被加密,所以我们插入的用户密码应该是被加密的。

这里假如我们使用的密码为admin,则加密过后的字符串是 $2a$04$1OiUa3yEchBXQBJI8JaMyuKZNlwzWvfeQjKAHnwAEQwnacjt6ukqu

 测试类如下 :

package com.wuxicloud.security;

import org.junit.Test;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * Created by EalenXie on 2018/7/11 15:13
 */
public class TestEncoder {

 @Test
 public void encoder() {
 String password = "admin";
 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(4);
 String enPassword = encoder.encode(password);
 System.out.println(enPassword);
 }
}

测试登录,从上面的加密的密码我们插入一条数据到数据库中。

INSERT INTO `USER` VALUES (1, 'd242ae49-4734-411e-8c8d-d2b09e87c3c8', 'EalenXie', '$2a$04$petEXpgcLKfdLN4TYFxK0u8ryAzmZDHLASWLX/XXm8hgQar1C892W', 'SSSSS', 'ssssssssss', 1, 'g', '0:0:0:0:0:0:0:1', '2018-07-11 11:26:27');

13 . 启动项目进行测试 ,访问 localhost:8083

点击登录,登录失败会留在当前页面重新登录,成功则进入index.html

登录如果成功,可以看到后台打印登录成功的日志 :

页面进入index.html :

点击注销 ,则回重新跳转到login.html,后台也会打印登出成功的日志 :

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • SpringBoot2.0整合jackson配置日期格式化和反序列化的实现

    网上杂七杂八的说法不一,大多数都是抄来抄去,没有实践,近期在项目频繁遇到boot+jackson处理日期的问题,故开此贴. 首先是POM <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance

  • SpringBoot2.x 整合Spring-Session实现Session共享功能

    1.前言 发展至今,已经很少还存在单服务的应用架构,不说都使用分布式架构部署, 至少也是多点高可用服务.在多个服务器的情况下,Seession共享就是必须面对的问题了. 解决Session共享问题,大多数人的思路都是比较清晰的, 将需要共享的数据存在某个公共的服务中,如缓存.很多人都采用的Redis,手动将Session存在Redis,需要使用时,再从Redsi中读取数据.毫无疑问,这种方案是可行的,只是在手动操作的工作量确实不少. LZ在这里采用的Spring-Session来实现.它使用代理

  • 详解基于Spring Boot/Spring Session/Redis的分布式Session共享解决方案

    分布式Web网站一般都会碰到集群session共享问题,之前也做过一些Spring3的项目,当时解决这个问题做过两种方案,一是利用nginx,session交给nginx控制,但是这个需要额外工作较多:还有一种是利用一些tomcat上的插件,修改tomcat配置文件,让tomcat自己去把Session放到Redis/Memcached/DB中去.这两种各有优缺,也都能解决问题. 但是现在项目全线Spring Boot,并不自己维护Tomcat,而是由Spring去启动Tomcat.这样就会有一

  • Spring boot Mybatis 整合(完整版)

    本项目使用的环境: 开发工具: Intellij IDEA 2017.1.3 springboot: 1.5.6 jdk:1.8.0_161 maven:3.3.9 额外功能 PageHelper 分页插件 mybatis generator 自动生成代码插件 步骤: 1.创建一个springboot项目: 2.创建项目的文件结构以及jdk的版本 3.选择项目所需要的依赖 然后点击finish 5.看一下文件的结构: 6.查看一下pom.xml: <?xml version="1.0&qu

  • 详解springboot中redis的使用和分布式session共享问题

    对于分布式使用Nginx+Tomcat实现负载均衡,最常用的均衡算法有IP_Hash.轮训.根据权重.随机等.不管对于哪一种负载均衡算法,由于Nginx对不同的请求分发到某一个Tomcat,Tomcat在运行的时候分别是不同的容器里,因此会出现session不同步或者丢失的问题. 实际上实现Session共享的方案很多,其中一种常用的就是使用Tomcat.Jetty等服务器提供的Session共享功能,将Session的内容统一存储在一个数据库(如MySQL)或缓存(如Redis)中. 本文旨在

  • Spring Boot高级教程之使用Redis实现session共享

    Redis是一个缓存消息中间件及具有丰富特性的键值存储系统.Spring Boot为Jedis客户端库和由Spring Data Redis提供的基于Jedis客户端的抽象提供自动配置.spring-boot-starter-redis'Starter POM'为收集依赖提供一种便利的方式. 引入spring-boot-starter-redis,在pom.xml配置文件中增加配置如下(基于之前章节"Spring Boot 构建框架"中的pom.xml文件): <dependen

  • springboot整合vue项目(小试牛刀)

    序 本文主要研究一下如何在springboot工程整合vue maven <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 新建springboot的web工程,默认会在resources目录下生成static以及templates文件夹 temp

  • spring boot整合redis实现shiro的分布式session共享的方法

    我们知道,shiro是通过SessionManager来管理Session的,而对于Session的操作则是通过SessionDao来实现的,默认的情况下,shiro实现了两种SessionDao,分别为CachingSessionDAO和MemorySessionDAO,当我们使用EhCache缓存时,则是使用的CachingSessionDAO,不适用缓存的情况下,就会选择基于内存的SessionDao.所以,如果我们想实现基于Redis的分布式Session共享,重点在于重写Session

  • SpringBoot2.0整合SpringCloud Finchley @hystrixcommand注解找不到解决方案

    hystrix参数使用方法 通过注解@HystrixCommand的commandProperties去配置, 如下就是hystrix命令超时时间命令执行超时时间,为1000ms和执行是不启用超时 @RestController public class MovieController { @Autowired private RestTemplate restTemplate; @GetMapping("/movie/{id}") @HystrixCommand(commandPro

  • Spring Boot整合Spring Security简单实现登入登出从零搭建教程

    前言 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作. 本文主要给大家介绍了关于Spring Boot整合S

  • spring boot整合scurity做简单的登录校验的实现

    开发环境:springboot maven引入: <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> &

  • Spring Boot整合Spring Security的示例代码

    本文讲述Spring Boot整合Spring Security在方法上使用注解实现权限控制,使用自定义UserDetailService,从MySQL中加载用户信息.使用Security自带的MD5加密,对用户密码进行加密.页面模板采用thymeleaf引擎. 源码地址:https://github.com/li5454yong/springboot-security.git 1.引入pom依赖 <parent> <groupId>org.springframework.boot

  • Spring Boot整合Spring Data JPA过程解析

    Spring Boot整合Spring Data JPA 1)加入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> &l

  • Spring Boot整合Spring Cache及Redis过程解析

    这篇文章主要介绍了Spring Boot整合Spring Cache及Redis过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.安装redis a.由于官方是没有Windows版的,所以我们需要下载微软开发的redis,网址: https://github.com/MicrosoftArchive/redis/releases b.解压后,在redis根目录打开cmd界面,输入:redis-server.exe redis.wind

  • Spring Boot整合logback一个简单的日志集成架构

    一.业务需求 在项目开发和运维过程中需要通过日志来分析问题,解决问题以保证项目的正常运行.通过SpringBoot自带的日志管理相对比较简单,已无法满足日常的运维需求,需要对日志文件进行分时分类管理,刚好通过学习接触到了logback日志系统.因此便决定将其加入到项目框架之中. 二.logback简介 至于简介,可自行网上查阅相关文档文献,这里不做详细描述,毕竟不是本文主要目的.只需理解它很好的实现了slf4j,是log4j的再发展即可. 三.具体实施方案(仅供参考) 1.引入依赖包 其实不需要

  • Spring Boot整合Spring Data Jpa代码实例

    一.Spring Data Jpa的简介 spring data:其实就是spring 提供的一个操作数据的框架.而spring data JPA 只是spring data 框架下的一个基于JPA标准操作数据的模块. spring data jpa :基于JPA的标准对数据进行操作.简化操作持久层的代码,只需要编写接口就可以,不需要写sql语句,甚至可以不用自己手动创建数据库表. 二.添加依赖 <!--添加springdatajpa的依赖--> <dependency> <

  • Spring Boot整合ELK实现日志采集与监控

    目录 Spring Boot整合ELK实现日志采集与监控 前言 架构图示 ELK搭建 Spring Boot工程配置 验证 查看logstash是否接收到日志 查看索引是否已经生效 日志分析 结语 Spring Boot整合ELK实现日志采集与监控 前言 在分布式项目中,可以采用ELK来作为日志的收集与分析系统,提供一个统一的入口来对日志进行收集,访问和管理.本文主要演示Spring Boot项目与ELK整合来实现日志的采集与监控. 架构图示 本次测试工程中,采用的架构如下图所示,微服务通过TC

  • Spring Boot 整合持久层之Spring Data JPA

    目录 整合Spring Data JPA 1. 创建数据库 2. 创建项目 3. 数据库配置 4. 创建实体类 5. 创建 BookDao 接口 6. 创建 BookService 7. 创建 BookController 8. 测试 整合Spring Data JPA JPA (Java Persistence API)和 Spring Data 是两个范畴的概念. Hibernate 是一个 ORM 框架,JPA 则是一种ORM,JPA 和 Hibernate 的关系就像 JDBC 与 JD

随机推荐