记录编写监听器时无法通过’@Autowired‘获取业务类的问题

前几天需要编写一个session监听器,直接写了个类来实现HttpSessionListener接口,HttpSessionListener中有两个方法需要重写(实现),一个是sessionCreated(HttpSessionEvent se),这个方法是session创建时触发的;一个方法是sessionDestroyed(HttpSessionEvent se),这个方法是session失效时会触发的;很简单,写完方法再在web.xml中配置一下监听器就行,配置代码如下:

<listener>

    <listener-class>com.netvour.commons.listener.SessionListener</listener-class> 

</listener>

但等我真正应用到这监听器却一直报空指针异常,debug后才发现,原来

@Autowired

private SysUserService sysUserService; 

拿到的是null,上网查了才知道,监听器是属于servlet容器的,而不是spring 管理的, 无法通过应用spring的注解去引入业务类对象(-_-|||)~~


既然知道问题了,接下来就是找解决方式了。 直接在实现一个接口,ServletContextListener接口,它能够监听 ServletContext 对象的生命周期,实际上就是监听 Web 应用的生命周期。

ServletContextListener有两个方法需要重写(实现),一个是contextInitialized(ServletContextEvent sce)方法,当Servlet 容器启动Web 应用时调用该方法。在调用完该方法之后,容器再对Filter 初始化,并且对那些在Web 应用启动时就需要被初始化的Servlet 进行初始化;一个是contextDestroyed(ServletContextEvent sce)方法,当Servlet 容器终止Web 应用时调用该方法。(在调用该方法之前,容器会先销毁所有的Servlet 和Filter 过滤器)。

而我们需要做的就是,在contextInitialized(ServletContextEvent sce)中,获取到业务类对象,代码如下:


public class SessionListener implements ServletContextListener,HttpSessionListener{

private SysUserService sysUserService;

@Override
public void sessionCreated(HttpSessionEvent se) {}

@Override
public void sessionDestroyed(HttpSessionEvent se) {

//业务方法
SysUserLoginVo so = (SysUserLoginVo) se.getSession().getAttribute("user");
if(so!=null){
SysUserLoginVo tmp = new SysUserLoginVo();
tmp.setStatus(2);
boolean flag = sysUserService.updateSysUserInfo("listener",tmp);
if(flag){
     System.out.println("session过期,自动更新用户状态成功");
}else{
     System.out.println("session过期,自动更新用户状态失败");
}
}
}

@Override
public void contextInitialized(ServletContextEvent sce) {

        ServletContext servletContext = sce.getServletContext();  
        ApplicationContext context = (ApplicationContext) servletContext.getAttribute(  
                WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); 
 
          
        //initialize service when spring context initialized,  
        //建立对应的service当spring上下文初始化之后  
        //使用spring框架中已经初始化的sysUserService 
        sysUserService = (SysUserService)context.getBean(SysUserService.class); 
}

@Override
public void contextDestroyed(ServletContextEvent sce) {}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,使用 Spring Boot 编写 Netty 登录流程,可以按照以下步骤进行: 1. 引入 Netty 和 Spring Boot 的依赖。 2. 编写 Netty 服务器端的业务逻辑,实现登录功能。可以使用 Netty 的 ChannelInboundHandlerAdapter 类,重载 channelRead 方法实现登录逻辑。例如: ``` public class LoginServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //1.解析登录请求数据 LoginRequestPacket loginRequestPacket = (LoginRequestPacket) msg; //2.验证登录请求数据 LoginResponsePacket loginResponsePacket = loginVerify(loginRequestPacket); //3.发送登录结果 ctx.channel().writeAndFlush(loginResponsePacket); } private LoginResponsePacket loginVerify(LoginRequestPacket loginRequestPacket){ //根据登录请求数据进行验证 //... return new LoginResponsePacket(); } } ``` 3. 在 Spring Boot 中创建 Netty 服务器,并将 Netty 服务器端的业务逻辑注册到 Netty 服务器中。可以使用 Spring Boot 的 @Configuration 和 @Bean 注解实现,例如: ``` @Configuration public class NettyServerConfig { @Bean(name = "nettyServerBootstrap") public ServerBootstrap bootstrap() { //1.创建 bossGroup 和 workerGroup EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); //2.创建 Netty 服务器 ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { //3.将 Netty 服务器端的业务逻辑注册到 Netty 服务器中 socketChannel.pipeline().addLast(new LoginServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); return serverBootstrap; } @Bean(name = "nettyServerSocketAddress") public InetSocketAddress tcpPort() { //4.设置 Netty 服务器监听的端口号 return new InetSocketAddress(8080); } @Bean(name = "nettyServer") public ChannelFuture tcpServer(@Qualifier("nettyServerBootstrap") ServerBootstrap bootstrap, @Qualifier("nettyServerSocketAddress") InetSocketAddress address) { //5.启动 Netty 服务器 return bootstrap.bind(address); } } ``` 4. 在 Spring Boot 的控制器中编写登录接口,接收登录请求数据,将登录请求数据发送给 Netty 服务器进行验证,并返回登录结果给客户端。例如: ``` @RestController @RequestMapping("/user") public class UserController { @Autowired private ChannelGroup channelGroup; @PostMapping("/login") public void login(@RequestBody LoginRequestPacket loginRequestPacket) { //1.获取 Netty 服务器的 Channel Channel channel = channelGroup.iterator().next(); //2.向 Netty 服务器发送登录请求数据 channel.writeAndFlush(loginRequestPacket); } @MessageMapping("/login-response") public void loginResponse(LoginResponsePacket loginResponsePacket) { //3.将登录结果返回给客户端 //... } } ``` 5. 在 Netty 服务器端的业务逻辑中,根据登录请求数据进行验证,如果验证成功,则向客户端发送数据;如果验证失败,则向客户端发送登录失败。例如: ``` public class LoginServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //1.解析登录请求数据 LoginRequestPacket loginRequestPacket = (LoginRequestPacket) msg; //2.验证登录请求数据 LoginResponsePacket loginResponsePacket = loginVerify(loginRequestPacket); //3.发送登录结果 ctx.channel().writeAndFlush(loginResponsePacket); //4.如果验证成功,则向客户端发送数据;如果验证失败,则向客户端发送登录失败 if (loginResponsePacket.isSuccess()) { ctx.channel().writeAndFlush(new MessageResponsePacket("登录成功!")); } else { ctx.channel().writeAndFlush(new MessageResponsePacket("登录失败!")); } } private LoginResponsePacket loginVerify(LoginRequestPacket loginRequestPacket){ //根据登录请求数据进行验证 //... return new LoginResponsePacket(); } } ``` 以上就是使用 Spring Boot 编写 Netty 登录流程的基本步骤,具体实现可以根据实际需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值