Netty网络聊天室之使用spring管理各种组件

原创 2017年08月10日 21:04:16
Spring是web开发的宠儿,不管mvc框架选择structs还是SpringMVC,IOC容器都是选择Spring。Spring有两个主要的作用,一个是IOC(依赖注入),另一个是AOP(面向切面编程)。只要是java项目,就可以使用这个框架。
在这里,我不过多对Spring进行布道。说一下有没有使用Spring的编码习惯。若不采用Spring进行项目开发,我们每个类一般都是采用单例的模式,例如 UserService.getInstance();使用了Spring,就只需要在UserService加个注解就可以把它丢入spring容器(Spring默认创建对象就是使用单例模式)。如果其他模块需要调用UserService的接口,只需要从spring容器把它拿出来即可,非常方便。

对于没有接触Spring的童鞋,只需要知道Spring是一个巨大的对象容器。使用@Component,@Servoce,@Controller,@Repository可以把对象放入容器,使用@Resource,@Autowired可以从容器里取对象。

spring管理组件的配置方式

1. 项目里受spring管理的组件是非常多的,所以我们需要能让spring容器自动扫描所有组件,只需要在spring配置加上这一行就可以了

<context:component-scan base-package="com.kingston" />
2. 把组件交给spring容器管理,配置如下

@Repository
public interface UserDao 
3. 使用Spring容器里的对象,配置如下

@Component
public class LoginService {

	@Autowired
	private UserDao userDao;
}

需要特别注意的是,这里用Autowired注解从spring里拿对象,LoginService本身也必须受spring管理,否则就需要手动从spring获取bean。

缓存Spring容器本身引用

1. 不是所有对象都放在spring容器里的。若某个对象本身没有放入spring里,想要拿spring容器的组件,就只能从spring的容器上下文环境中获取。所以,有必要把这个spring容器上下文缓存起来。要获取spring容器,只需要类实现ApplicationContextAware这个接口即可。像这样

public class SpringContext implements ApplicationContextAware {
	/** spring容器上下文 */
	private static ApplicationContext applicationContext = null;
	/** 异步持久化服务 */
	private static AysncDbService aysncDbService;
	
	private static ChatService chatService;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		SpringContext.applicationContext = applicationContext;
	}
	
	public final static <T> T getBean(Class<T> clazz) {
		return applicationContext.getBean(clazz);
	}
	
	public final static <T> Collection<T> getBeansOfType(Class<T> clazz) {
		return applicationContext.getBeansOfType(clazz).values();
	}
	
	public final static <T> T getBean(String name, Class<T> requiredType) {
		return applicationContext.getBean(name, requiredType);
	}

	@Resource
	public void setAysncDbService(AysncDbService aysncDbService) {
		SpringContext.aysncDbService = aysncDbService;
	}
	
	public static AysncDbService getAysncDbService() {
		return aysncDbService;
	}
	
	@Resource
	public void setChatService(ChatService chatService) {
		SpringContext.chatService = chatService;
	}
	
	public final static ChatService getChatService() {
		return chatService;
	}
	
}
并把SpringContext配置成spring的组件

	<!-- 注册spring上下文环境 -->
	<bean id="context" class="com.kingston.base.SpringContext" />
2. 非spring管理的实例想要获取spring组件,就可以像这样子了
	AbstractPacket  packet = (AbstractPacket)msg;
	System.err.println("receive pact, content is " + packet.getClass().getSimpleName());
	if(packet.getPacketType() == PacketType.ReqUserLogin ){
		ReqUserLoginPacket loginPact = (ReqUserLoginPacket)packet;
		
		LoginService loginMgr = SpringContext.getBean(LoginService.class);
		loginMgr.validateLogin(context,loginPact.getUserId(), loginPact.getUserPwd());
		return ;
	}

spring与mybatics的结合

使用了spring之后,数据库连接的数据源,以及Mybatics的SqlSessionFactoryBean就统统在spring进行配置就可以了。

1. 使用mybatis-spring库(mybatics整合spring的工具库),可以直接让spring扫描所有mybatics的mapper配置

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="config/mybatis-config.xml" />
		<!-- 自动扫描所有mapper配置 -->
		<property name="mapperLocations"
			value="classpath:com/kingston/data/mybatis/*Mapper.xml" />
	</bean>
2. 使用mybatis-spring库,可以自动扫描所有dao并注入到spring容器
	<!-- 自动扫描所有dao并注入到spring容器 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.kingston.data.dao" />
	</bean>

3. 这样一来,mybatics本身的配置就变得可有可无啦。不过,一些组件的别名申明还是可以放到mybatics的配置里

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!--别名申明 -->
	<typeAliases>
		<typeAlias type="com.kingston.data.model.User" alias="user" />
	</typeAliases>
	
</configuration>
UserMapper.xml配置里的 resultType="user" ,这里的 "user"就指向上面的完整类路径
<?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.kingston.data.dao.UserDao">
	<select id="findById" parameterType="java.lang.Long"
		resultType="user">
		select * from user where userId=#{userId}
	</select>
	<insert id="addUser" parameterType="user">
		insert into user(userId,userName,authentication) 
			values(#{userId},#{userName},#{authentication})
	</insert>
	<update id="updateUser" parameterType="user">
		update user
		set
		userName=#{userName}
		where userId=#{userId}
	</update>
	<delete id="delUser" parameterType="java.lang.Long">
		delete from user
		where
		userId=#{userId}
	</delete>
</mapper>

Spring结合Groovy脚本实现热部署

Groovy是JVM上的一门脚本语言,当Spring遇上了Groovy,就会缔造完美的效果。当部分spring组件需要在程序运行过程中实现代码热部署,只需要用Groovy的类加载器加载。具体的操作可以看下点击打开链接 这篇文章。
在实际使用环境,我们把需要热更新的代码统一放到src/groovy目录下。需要注意的是,ides开发环境跟jar包生产环境获取groovy目录的spring组件的方式是不同的。
在ide环境,只要将src/groovy目录标记为代码根目录,spring容器启动的时候,就可以扫描到groovy目录下被spring注解标记的组件。
在生产环境,我们使用maven作为打包工具,但maven 默认只把src/main目录下的java文件编译到目标jar包,我们自定义的src/groovy目录是不会打进包里的。这样更好,因为我们本来就不希望我们的groovy目录被编译成class。
我们希望groovy的目录与jar包分离,并且以源码的形式存在。当需要更新groovy里某个文件的代码时,直接替换文件即可。GroovyFactory类在扫描的时候,只要把扫描的根目录指向跟jar包同一目录下的groovy,也可以拿到groovy的spring组件。


全部代码已在github上托管

服务端代码请移步 --> netty聊天室服务器

客户端代码请移步 --> netty聊天室客户端





版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

淘淘商城系列——实现图片上传功能

上文我们使用FastDFS-Client进行了简单的文件上传操作测试,淘淘商城项目中添加商品时上传图片的功能还没实现,如下图所示。本文将花大量笔墨来教大家如何实现图片上传这个功能。 我们来看下i...

netty长连接实例

通过netty实现服务端与客户端的长连接通讯,及心跳检测。        基本思路:netty服务端通过一个Map保存所有连接上来的客户端SocketChannel,客户端的Id作为Map的ke...

Tomcat学习总结(7)——Tomcat与Jetty比较

Jetty 基本架构 Jetty目前的是一个比较被看好的 Servlet 引擎,它的架构比较简单,也是一个可扩展性和非常灵活的应用服务器。 它有一个基本数据模型,这个数据模型就是 Handl...

搭建一个后台服务器--客户端

上篇规定的协议请求部分: request: username/password, 约定username与password  各占32个字节(联同末位0) 可以将客户端的逻...

Netty 实现 WebSocket 聊天功能

上一次我们用 [Netty](http://netty.io/) 快速实现了一个 Java 聊天程序(见)。现在,我们要做下修改,加入 WebSocket 的支持,使它可以在浏览器里进行文本聊天。

淘淘商城系列——使用Spring来管理Redis单机版和集群版

我们知道Jedis在处理Redis的单机版和集群版时是完全不同的,有可能在开发的时候使用的是单机版,但是当项目上线后使用的则是集群版,这就需要能够方便的在单机版和集群版之间进行切换。我们的做法便是定义...

淘淘商城系列——单点登录接口文档分析

在工作当中,开发文档是我们开发人员最重要的开发指南,对开发文档一定要认真研读,不可错过任何重要信息,我们现在学单点登录(SSO)也需要学习下开发文档。 我们先来看文档的第一个接口(注册接口):检查数...

Mysql学习总结(17)——MySQL数据库表设计优化

1.选择优化的数据类型 MySQL支持很多种不同的数据类型,并且选择正确的数据类型对于获得高性能至关重要。不管选择何种类型,下面的简单原则都会有助于做出更好的选择: (1).更小通常更好 ...

搭建一个后台服务器--服务端(阻塞)

为什么 要在标题后面加个“阻塞”呢,因为系统为了增大并发,减小等待(阻塞),建立了另一种事件模式,后文将介绍,这里只介绍阻塞的模型。 阻塞服务器要干的事大致可以分为以下几步: 1.创建服务端监听连...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)