标签:
这里比较复杂的莫过于spring的配置了那就先上配置applicationContext.xml
mina的配置在最下面
<spring -- mina >这个 之上的 配置有velocity和memcache还有springjdbc,自动装配,json对象支持(注解@ResponseBody), 切面事务管理 , 当然这些大家能用的上的 拿走 用不上删掉(跟没说一样)
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="stringConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
</list>
</property>
</bean>
<bean id="exceptionResolver" class="com.util.ExceptionHandler"/>
<!-- 输出对象转JSON支持 -->
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="stringConverter"/>
<ref bean="jsonConverter" />
</list>
</property>
</bean>
<!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 -->
<!-- <context:component-scan base-package="com.controller" />
<context:component-scan base-package="com.service" />
<context:component-scan base-package="com.dao" /> -->
<context:component-scan base-package="com" />
<!-- 配置数据源 destroy-method="close"-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<!--连接池中保留的最小连接数。 -->
<property name="minPoolSize">
<value>5</value>
</property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">
<value>30</value>
</property>
<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize">
<value>10</value>
</property>
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime">
<value>60</value>
</property>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement">
<value>5</value>
</property>
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 -->
<property name="maxStatements">
<value>0</value>
</property>
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod">
<value>60</value>
</property>
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts">
<value>30</value>
</property>
<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
获取连接失败后该数据源将申明已断开并永久关闭。Default: false -->
<property name="breakAfterAcquireFailure">
<value>true</value>
</property>
<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。Default: false -->
<property name="testConnectionOnCheckout">
<value>false</value>
</property>
<property name="automaticTestTable">
<value>true</value>
</property>
</bean>
<!-- 配置Jdbc模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource" />
<!-- 通过AOP配置提供事务增强,让controller包下所有Bean的所有方法拥有事务 -->
<!-- <aop:config proxy-target-class="true">
<aop:pointcut id="serviceMethod"
expression=" execution(* com.controller..*(..))" />
<aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice> -->
<!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<!-- VM视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="requestContextAttribute" value="rc"></property>
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".vm"/>
<property name="contentType"><value>text/html;charset=UTF-8</value></property>
<property name="dateToolAttribute"><value>dateTool</value></property>
<property name="numberToolAttribute"><value>numberTool</value></property>
</bean>
<!-- 指定模板视图存放位置,以及编码格式 -->
<bean id="velocityConfigurer" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath" value="/WEB-INF/velo/"/>
<property name= "velocityProperties">
<props>
<prop key="input.encoding">utf-8</prop>
<prop key="output.encoding">utf-8</prop>
</props>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<!-- 访问数据库前,查询MEMCACHED缓存服务器 -->
<!-- <bean id="memcachedInterceptor" class="com.interceptor.MemcachedInterceptor"></bean>
<aop:config>
<aop:pointcut expression="execution(* select*(..))"
id="memcachedPointCut"/>
<aop:aspect id="memcachedAspect" ref="memcachedInterceptor">
<aop:around pointcut-ref="memcachedPointCut" method="aronud"/>
</aop:aspect>
</aop:config> -->
<!-- 官方文档地址 http://code.google.com/p/xmemcached/wiki/Spring_Integration -->
<bean
id="memcachedClientBuilder"
class="net.rubyeye.xmemcached.XMemcachedClientBuilder"
p:connectionPoolSize="20"
p:failureMode="true">
<constructor-arg>
<list>
<bean class="java.net.InetSocketAddress">
<constructor-arg>
<value>114.215.118.235</value>
</constructor-arg>
<constructor-arg>
<value>11211</value>
</constructor-arg>
</bean>
<!-- <bean class="java.net.InetSocketAddress"> -->
<!-- <constructor-arg> -->
<!-- <value>192.168.1.2</value> -->
<!-- </constructor-arg> -->
<!-- <constructor-arg> -->
<!-- <value>10002</value> -->
<!-- </constructor-arg> -->
<!-- </bean> -->
<!-- <bean class="java.net.InetSocketAddress"> -->
<!-- <constructor-arg> -->
<!-- <value>192.168.1.3</value> -->
<!-- </constructor-arg> -->
<!-- <constructor-arg> -->
<!-- <value>10003</value> -->
<!-- </constructor-arg> -->
<!-- </bean> -->
<!-- <bean class="java.net.InetSocketAddress"> -->
<!-- <constructor-arg> -->
<!-- <value>192.168.1.4</value> -->
<!-- </constructor-arg> -->
<!-- <constructor-arg> -->
<!-- <value>4</value> -->
<!-- </constructor-arg> -->
<!-- </bean> -->
</list>
</constructor-arg>
<constructor-arg>
<list>
<value>1</value>
<!-- <value>2</value> -->
<!-- <value>3</value> -->
<!-- <value>4</value> -->
</list>
</constructor-arg>
<property name="commandFactory">
<bean class="net.rubyeye.xmemcached.command.TextCommandFactory" />
</property>
<property name="sessionLocator">
<bean class="net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator" />
</property>
<property name="transcoder">
<bean class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" />
</property>
</bean>
<bean
id="memcachedClient"
factory-bean="memcachedClientBuilder"
factory-method="build"
destroy-method="shutdown" />
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
p:defaultEncoding="utf-8"/>
<mvc:interceptors>
<!-- 拦截所有请求
<bean class="com.etoak.util.LoginCheck2"></bean>-->
<mvc:interceptor>
<mvc:mapping path="/dashboard"/>
<mvc:mapping path="/dashboard/**"/>
<mvc:mapping path="/setting"/>
<mvc:mapping path="/setting/**"/>
<bean class="com.interceptor.LoginCheck"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.interceptor.CityCheck"></bean>
</mvc:interceptor>
</mvc:interceptors>
<!-- spring && mina -->
<!-- executorFilter多线程处理 -->
<bean id="executorFilter" class="org.apache.mina.filter.executor.ExecutorFilter" />
<bean id="mdcInjectionFilter" class="org.apache.mina.filter.logging.MdcInjectionFilter">
<constructor-arg value="remoteAddress" />
</bean>
<bean id="codecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter">
<constructor-arg>
<!-- <bean class="org.apache.mina.filter.codec.textline.TextLineCodecFactory" />-->
<!-- 处理对象流时候用ObjectSerializationCodecFactory -->
<!-- <bean class="org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory" /> -->
<bean class="com.umaiw.socket.ServerCodeFactory" />
</constructor-arg>
</bean>
<bean id="loggingFilter" class="org.apache.mina.filter.logging.LoggingFilter" />
<bean id="filterChainBuilder" class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder">
<property name="filters">
<map>
<entry key="executor" value-ref="executorFilter" />
<entry key="mdcInjectionFilter" value-ref="mdcInjectionFilter" />
<entry key="codecFilter" value-ref="codecFilter" />
<entry key="loggingFilter" value-ref="loggingFilter" />
</map>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.net.SocketAddress">
<bean class="org.apache.mina.integration.beans.InetSocketAddressEditor" />
</entry>
</map>
</property>
</bean>
<!-- session config -->
<bean id="sessionConfig" factory-bean="ioAcceptor"
factory-method="getSessionConfig" >
<property name="readerIdleTime" value="50"/>
</bean>
<bean id="ioAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor" init-method="bind" destroy-method="unbind">
<property name="defaultLocalAddress" value=":10000" />
<property name="handler" ref="dataHandler" />
<property name="filterChainBuilder" ref="filterChainBuilder" />
<property name="reuseAddress" value="true" />
</bean>
<bean id="dataHandler" class="com.umaiw.socket.DataHandler">
</bean>
<bean id="udpAcceptor" class="org.apache.mina.transport.socket.nio.NioDatagramAcceptor" init-method="bind" destroy-method="unbind">
<property name="defaultLocalAddress" value=":10001" />
<property name="handler" ref="UdpHandler" />
<property name="filterChainBuilder" ref="filterChainBuilder" />
</bean>
<bean id="UdpHandler" class="com.umaiw.socket.UdpHandler">
</bean>
</beans>
然后是DataHandler 处理各种事件的地方
package com.umaiw.socket;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.IoFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.model.UserSession;
import com.model.umaiw_app_system;
import com.service.GetInitKeyService;
import com.service.implement.GetInitKeyServiceImpl;
import com.umaiw.command.Command;
import com.umaiw.command.Constants;
import com.umaiw.command.SocketModel;
import com.util.DesUtil;
@Component("DataHandler")
public class DataHandler extends IoHandlerAdapter implements Runnable{
@Autowired
private Constants constants;
private final static Logger log = LoggerFactory.getLogger(DataHandler.class);
private final Set<IoSession> sessions = Collections.synchronizedSet(new HashSet<IoSession>());
//private UserSession UserSession;
@Autowired
private static Map<String,IoSession> users = Collections.synchronizedMap(new HashMap<String,IoSession>());
@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
log.error(" 有异常发生时被触发exceptionCaught。",cause);
session.close(true);
}
@Override
public void sessionCreated(IoSession session) throws Exception {
log.info("当创建一个新连接时被触发,即当开始一个新的Session时被触发。");
log.info("创建一个新连接:{}", session.getRemoteAddress());
/*//50秒无读写操作就触发idele
session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 50);*/
sessions.add(session);
log.info("并发的个数:\t"+sessions.size());
//TODO
messageSentSingle(session, "");
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
log.info("服务器接收到数据: {}", message);
Command cmd = (Command)constants.newCommand(message);
cmd.action(session, other);
messageSentSingle(session, "业务处理完了");
}
public static void messageSentAll( Object message) throws Exception {
log.info("发送消息时时被触发,即在调用IoSession.write()时被触发,message代表将要发送的消息。=" + message);
// 向所有客户端发送的数据
SocketModel socm=new SocketModel(new Date().getTime()+"", "", 5, message);
String send=socm.toString();
Collection<IoSession> sessions = users.values();
for (IoSession sess : sessions) {
sess.write(send);
}
}
public static void messageSentSingle(IoSession session, Object message) throws Exception {
log.info("发送消息时时被触发,即在调用IoSession.write()时被触发,message代表将要发送的消息。=" + message);
// 向所有客户端发送的数据
Integer command=(Integer) session.getAttribute("command");
SocketModel socm=new SocketModel(new Date().getTime()+"", "", command, message);
String send=socm.toString();
session.write(send);
}
public static void messageSentPart( Object message,String city_id) throws Exception {
log.info("发送消息时时被触发,即在调用IoSession.write()时被触发,message代表将要发送的消息。=" + message);
Object[] key=users.keySet().toArray();
for (int i = 0; i < key.length; i++) {
if(key[i].toString().contains(city_id)){
IoSession iosession=users.get(key[i]);
SocketModel socm=new SocketModel(new Date().getTime()+"", "", 5, message);
String send=socm.toString();
iosession.write(send);
}
}
// 向所有客户端发送的数据
}
public static Map<String, IoSession> getUsers() {
return users;
}
@Override
public void sessionClosed(IoSession session) throws Exception {
log.info("关闭当前session:{}#{}", session.getId(), session.getRemoteAddress());
CloseFuture closeFuture = session.close(true);
closeFuture.addListener(new IoFutureListener<IoFuture>() {
public void operationComplete(IoFuture future) {
if (future instanceof CloseFuture) {
((CloseFuture) future).setClosed();
log.info("sessionClosed CloseFuture setClosed-->{},", future.getSession().getId());
}
}
});
UserSession userSession= (UserSession) session.getAttribute("UserSession");
String mobile=(String) session.getAttribute("mobile");
if(null!=mobile&&userSession!=null){
users.remove(mobile+"+"+userSession.getCity_id());
}
sessions.remove(session);
log.info("关闭的连接的剩余的个数:\t"+sessions.size());
}
@Override
public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
// session.close();
log.info("IDLE " + session.getIdleCount(status)+"次;"+"user个数"+users.size()+"sessions个数"+sessions.size());
if(session.getIdleCount(status) > 5){
log.info("连接空闲= " + session.getIdleCount(status)+",触发session关闭");
session.close(true);
}
}
@Override
public void sessionOpened(IoSession session) throws Exception {
log.info("进入当打开一个连接时被触发sessionOpened!");
log.info("打开一个session:{}#{}", session.getId(), session.getBothIdleCount());
try {
super.sessionOpened(session);
} catch (Exception e) {
log.error("",e);
}
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
log.info("发送消息时时被触发,即在调用IoSession.write()时被触发,message代表将要发送的消息。=" + message);
try {
super.messageSent(session, message);
} catch (Exception e) {
log.error("",e);
}
}
}
}
未完待续。。。。。
spring,spring mvc ,mina,接收http请求然后调用mina给客户端发送信息
标签:
原文地址:http://my.oschina.net/angleshuai/blog/410960