说明
Spring-Netty-Mybatis的框架结构, 主要是提供socket入口.
pom就不放了, 全球通用. 配置也放了一些主要的. 做之前也是参考了很多网上大佬的帖子, 如有雷同.
(程序员的事怎么能叫抄呢)
配置文件
<description>Spring公共配置</description>
<context:annotation-config />
<!-- 这里是给出需要扫描的包的路径,一般是最外层. 表明使用annotation 自动注册bean,并检查@Required,@Autowired等属性并注入 -->
<context:component-scan base-package="com.mid.abc" />
<!-- 启动端口 -->
<!-- 这里因为是jar应用.所以提供了一个启动器 -->
<bean id="initServer" class="com.mid.abc.start.InitServer">
<property name="port" value="端口" />
</bean>
<!-- spring和MyBatis整合,不使用mybatis的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描mapping.xml文件,**表示迭代查找 -->
<property name="mapperLocations" value="classpath:mybatis/*.xml" />
</bean>
<!-- DAO接口所在包名,Spring会自动查找其下的类 ,包下的类需要使用@MapperScan注解,否则容器注入会失败 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mid.abc.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
<!-- 事务管理器, Jdbc单数据源事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 需开启, 否则无法自动注入 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<aop:config>
<!-- 这里的路径是再service包下还有一层文件夹(service.xxx.xxxService.java) -->
<aop:advisor pointcut="execution(* com.mid.abc.service.*..*.*(..))"
advice-ref="txAdvice" />
</aop:config>
启动类
public class RunServer {
public static void main(String[] args) throws UnknownHostException {
try {
// 1.加载spring
@SuppressWarnings("resource")
ApplicationContext act = new ClassPathXmlApplicationContext("/context/spring-context.xml");
// 2.获取initServer对象
InitServer bean = act.getBean(InitServer.class);
bean.run();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
netty初始化
@Component
public class InitServer {
private Logger log = LoggerFactory.getLogger(getClass());
/**
* socket通道Handler
*/
@Autowired
private ServerHandler serverHandler;
/**
* 服务启动端口号
*/
private Integer port;
/**
* 服务启动
*
* @throws Exception
*/
public void run() throws Exception {
log.info("Server Start......");
// EventLoopGroup是用来处理IO操作的多线程事件循环器
// bossGroup 用来接收进来的连接
EventLoopGroup bossGroup = new NioEventLoopGroup();
// workerGroup 用来处理已经被接收的连接
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// 启动 NIO 服务的辅助启动类
ServerBootstrap b = new ServerBootstrap();
log.debug("Init Channel......");
b.group(bossGroup, workerGroup)
// 配置 Channel
.channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
// 注册handler, 后续的netty相关操作就在serverHandler中了.
ch.pipeline().addLast(serverHandler);
}
}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);
log.info("Exposed IP Address: {} ......", java.net.InetAddress.getLocalHost().getHostAddress());
log.info("Binding On Port {} ......", port);
// 绑定端口,开始接收进来的连接
ChannelFuture f = b.bind(port).sync();
// 等待服务器 socket 关闭 。
f.channel().closeFuture().sync();
} finally {
log.info("Graceful Exit Server ......");
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
}
abstract类注入的问题
abstract类中需要注入的属性.
抽象类是无法实例化的, 所以无法注入bean. 因此需要在抽象类的子类中注入该属性, 再传递给父类, 而父类是不需要加什么注解的.如下:
// 这是父类
public abstract class Processor {
protected IDontKnowHer iDontKnowHer;
}
// 这是子类
@Service
public class MessageProcessor extends Processor {
//这里使用的init方法在autowired的作用下就会被优先调用并注入属性.传递bean给父类使用.
@Autowired
public void init(IDontKnowHer iDontKnowHer){
super.iDontKnowHer = iDontKnowHer;
}
}