初始化项目
1、新建一个 Spring Boot 项目,默认添加 web,然后等待构建完成,完成后目录结构如下:
.
├── HELP.md
├── login-session-demo.iml
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   ├── resources
│   │   └── webapp
│   └── test
│       └── java
└── target
 
pom文件
其中,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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.terwergreen</groupId>
    <artifactId>login-session-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>login-session-demo</name>
    <description>login-session-demo</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
 
创建登录控制器
2、创建 LoginController , 添加 @Controller 注解,并添加对应的方法
/**
 * 登录控制器
 *
 * @name: LoginController
 * @author: terwer
 * @date: 2022-01-24 16:36
 **/
@RequestMapping("/login")
@Controller
public class LoginController {
    @RequestMapping(value = "/toLogin", method = RequestMethod.GET)
    public String toLogin() {
        return "login";
    }
    @RequestMapping(value = "login", method = RequestMethod.POST)
    public String login(String username, String password) {
        if ("test".equals(username) && "test".equals(password)) {
            return "redirect:/result.jsp";
        }
        return "login";
    }
}
 
配置模板路径映射
3、配置 application.properties ,设置端口,springmvc的jsp模板前缀和后缀
server.port=8081
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
 
然后在main下面新增webapp/WEB-INF/jsp目录
再新建 login.jsp 文件。
4、此时会发生问题,访问 http://localhost:8081/login/toLogin 报错 404,控制台打印
原因:默认不支持jsp。需要在pom.xml加入下面的jar包以支持jsp
<!--jsp页面使用jstl标签 -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
</dependency>
<!--用于编译jsp -->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <scope>provided</scope>
</dependency>
 
重新加载pom.xml,然后重启项目,再次访问 http://localhost:8081/login/toLogin ,正确出现页面

热部署
5、添加热部署
为了修改文件能够及时看到效果,可以添加热部署插件。
<!-- 热部署 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>
 
添加拦截器实现登录验证
6、添加拦截器进行登录验证
创建登录拦截器
/**
 * 登录拦截器
 *
 * @name: LoginInterceptor
 * @author: terwer
 * @date: 2022-01-24 17:46
 **/
@Component
public class LoginInterceptor implements HandlerInterceptor {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 利用Session校验登录状态实现登录拦截
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("进入登录拦截器");
        HttpSession session = request.getSession();
        Object username = session.getAttribute(Constant.SESSION_USERNAME_KEY);
        if (null == username) {
            logger.info("未登录或者登录失效");
            response.sendRedirect(request.getContextPath() + "/login/toLogin");
            return false;
        }
        logger.info("从Session中获取的登录名:" + username);
        return true;
    }
}
 
注册登录拦截器到Spring Boot中去
/**
 * Spring  MVC自定义配置
 *
 * @name: MyWebMvcConfigAdaptor
 * @author: terwer
 * @date: 2022-01-24 17:51
 **/
@Configuration
public class MyWebMvcConfigAdaptor implements WebMvcConfigurer {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器
        // 默认拦截所有
        // 排除登录页面本身还有错误页面
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login/**", "/error");
        logger.info("登录拦截器已添加");
    }
}
 
集成mybatis
7、集成mybatis
mybatis集成
pom.xml加入mybatis依赖、mysql数据库
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.1</version>
</dependency>
<!--mysql驱动坐标-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.6</version>
    <scope>runtime</scope>
</dependency>
 
配置文件配置数据源、mybatis
# mybatis
mybatis.mapper-locations=classpath:com/terwergreen/dao/*.xml
# mysql
spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
 
创建Mapper
/**
 * 用户映射类
 *
 * @name: UserMapper
 * @author: terwer
 * @date: 2022-01-24 21:44
 **/
public interface UserMapper{
    public User findByCondition(User user);
}
 
mapper映射
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.terwergreen.dao.UserMapper">
    <select id="findByCondition" parameterType="com.terwergreen.pojo.User" resultType="com.terwergreen.pojo.User">
        select * from user where username=#{username} and password=#{password}
    </select>
</mapper>
 
service业务处理
/**
 * 登录业务
 *
 * @name: LoginServiceImpl
 * @author: terwer
 * @date: 2022-01-24 22:06
 **/
@Service
public class LoginServiceImpl implements LoginService {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private SqlSession session;
    public boolean doLogin(String username, String password) {
        logger.info("开始处理登录");
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);
        // User result = session.selectOne("findByCondition", user);
        UserMapper userMapper = session.getMapper(UserMapper.class);
        User result = userMapper.findByCondition(user);
        if (null != result) {
            logger.info("用户信息校验成功");
            return true;
        }
        logger.info("用户不存在或者密码错误");
        return false;
    }
}
 
常规实现优化以及问题
controller登录处理
    @RequestMapping(value = "login", method = RequestMethod.POST)
    public String login(String username, String password, HttpServletRequest request) {
        HttpSession session = request.getSession();
        if (loginService.doLogin(username, password)) {
            request.getSession().setAttribute(Constant.SESSION_USERNAME_KEY, username);
            session.setAttribute(Constant.SESSION_LOGIN_FAIL_MSG_KEY, "");
            return "redirect:/demo/result";
        }
        session.setAttribute(Constant.SESSION_LOGIN_FAIL_MSG_KEY, Constant.SESSION_LOGIN_FAIL_MSG);
        return "login";
    }
 
利用拦截器进行登录拦截
拦截器实现
新建 LoginInterceptor 实现 HandlerInterceptor 接口,在preHandle里面进行拦截
/**
 * 登录拦截器
 *
 * @name: LoginInterceptor
 * @author: terwer
 * @date: 2022-01-24 17:46
 **/
@Component
public class LoginInterceptor implements HandlerInterceptor {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 利用Session校验登录状态实现登录拦截
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("进入登录拦截器");
        HttpSession session = request.getSession();
        Object username = session.getAttribute(Constant.SESSION_USERNAME_KEY);
        if (null == username) {
            logger.info("未登录或者登录失效");
            // session.setAttribute( Constant.SESSION_LOGIN_FAIL_MSG_KEY, Constant.SESSION_LOGIN_FAIL_MSG);
            response.sendRedirect(request.getContextPath() + "/login/toLogin");
            return false;
        }
        session.setAttribute( Constant.SESSION_LOGIN_FAIL_MSG_KEY, "");
        logger.info("从Session中获取的登录名:" + username);
        return true;
    }
}
 
注册拦截器
/**
 * Spring  MVC自定义配置
 *
 * @name: MyWebMvcConfigAdaptor
 * @author: terwer
 * @date: 2022-01-24 17:51
 **/
@Configuration
public class MyWebMvcConfigAdaptor implements WebMvcConfigurer {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器
        // 默认拦截所有
        // 排除登录页面本身还有错误页面
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login/**", "/error");
        logger.info("登录拦截器已添加");
    }
}
 
session保存到redis解决问题
上面的实现在Nginx轮询策略的时候,会出现登录session不一致问题。解决方案是把session保存到redis。具体方法就是加上对应的starter即可无缝集成redis。
<!-- redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
 
部署验证
nginx配置
upstream loginServer{
   # 为了测试方便,使用127.0.0.1
   server 127.0.0.1:8080;
   server 127.0.0.1:8081;
   # server 192.168.136.134:8080;
   # server 192.168.136.134:8081;
}
server {
    # 监听的端口
    listen       80;
    server_name  localhost;
    #charset koi8-r;
    #access_log  logs/host.access.log  main;
    # 默认请求
    location / {
	    proxy_pass http://loginServer/;
        # root   html;
        # index  index.html index.htm;
    }
}
 
利用maven打包,然后把war包放到tomcat的webapps目录下即可。
最后访问测试。
如果是本地部署可以访问
http://127.0.0.1:8081/logindemo/login/toLogin
否则把127.0.0.1换成服务器ip即可。
具体细节可参考视频
https://www.bilibili.com/video/BV1xa411m7RC/
完整的代码
https://github.com/terwer/login-session-demo










