前几天,在sf这里也提过这个问题,但是仍未得到解决,上一个问题是这个在Service中注入Dao不成功,Dao为null。但根据大虾们的回答,我想再理顺一下这个项目的逻辑,免得各位看着都不懂我在说什么。本人是spring小白,整个项目环境搭建是前辈写下的,我只是根据他的方法来添加修改,所以有很多框架上的逻辑我并不是看得很懂。
我想实现的是——用多线程通过socket不断获取从客户端发送过来的消息,并对消息联系JDBC进行分析。
P.S.代码部分都只截取了重要的部分
我先放一下其中一个service和dao的实现:
1)ConcentratorService:
public interface ConcentratorService {
public List<Concentrator> getConcentratorListByMacAddresses(String[] macAddr) throws Exception;
}
2)ConcentratorServiceImpl:
@Service("ConcentratorService")
public class ConcentratorServiceImpl implements ConcentratorService{
@Autowired
ConcentratorDao concentratorDao;
public Concentrator findConcentratorByCaddress(String caddress) throws Exception{
// TODO Auto-generated method stub
return concentratorDao.findConcentratorByCaddress(caddress);
}
}
3)ConcentratorDao
public interface ConcentratorDao {
public List<Concentrator> getConcentratorListByMacAddresses(String[] macAddr) throws Exception;
}
4)ConcentratorDaoImpl
public class ConcentratorDaoImpl implements ConcentratorDao {
@Autowired
SessionFactory sessionFactory;
Session session = null;
Transaction tx = null;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory=sessionFactory;
}
@Override
public List<Concentrator> getConcentratorListByMacAddresses(String[] macAddr) throws Exception {
session = sessionFactory.openSession();
tx = session.beginTransaction();
StringBuffer sb = new StringBuffer("from Concentrator where caddress in (");
for(int i=0; i<macAddr.length; i++){
if(i==macAddr.length-1){
sb.append("?)");
}else{
sb.append("?,");
}
}
Query query=session.createQuery(sb.toString());
for(int i=0; i<macAddr.length; i++){
query.setParameter(i, macAddr[i]);
}
@SuppressWarnings("unchecked")
List<Concentrator> clist=query.list();
tx.commit();
session.close();
return clist;
}
}
这里再放一下datasource.xml,这个xml是用来配置bean的。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/gwsl?characterEncoding=gbk" /> <!-- ?characterEncoding=UTF-8&useOldAliasMetadataBehavior=true" -->
<property name="username" value="XXX" />
<property name="password" value=" XXX" />
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.streetLight.model.Concentrator</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean id="concentratorDao" class="com.streetLight.dao.ConcentratorDaoImpl"></bean>
<bean id="concentratorService" class="com.streetLight.services.ConcentratorServiceImpl"></bean>
</beans>
以防万一把web.xml也放一下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name></display-name>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/root-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/root-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
****这里之后就是想添加的功能的代码:****
RunSocket:
//@Component
public class RunSocket {
public static void main(String[] args) throws InterruptedException {
System.out.println("开始启动websocket");
WebSocketImpl.DEBUG = false;
int port = 8888; // 端口随便设置,只要不跟现有端口重复就可以
WebSocket s = null;
try {
s = new WebSocket(port);
} catch (UnknownHostException e) {
System.out.println("启动websocket失败!");
e.printStackTrace();
}
s.start();
System.out.println("启动websocket成功!");
System.out.println("开始启动ServerSocket");
ReceiveThread mReceiveThread = new ReceiveThread();
mReceiveThread.init();
mReceiveThread.start();
}
// 代码修改自:
// 作者: 手插口袋_
// 链接:http://www.imooc.com/article/12401
}
下面是thread和解析信息的代码:
ReceiveThread:(方案一)
public class ReceiveThread extends Thread {
private ApplicationContext ctx;
private SpringContextUtil scu;
static final int SOCKET_PORT_0 = 8800; // 端口号
static ServerSocket mServerTest = null;
static Socket mSocket = null;
static InputStream mInput = null;
byte[] buffer;
static final byte CONTROLLER_FAULT = (byte)0x90;
List<Area> alist=new ArrayList<Area>();
List<String> msgList=new ArrayList<String>();
ConcentratorService concentratorService;
public void init() {
buffer = new byte[65536];
//scu = new SpringContextUtil();
ctx = new FileSystemXmlApplicationContext("/WebRoot/WEB-INF/config/datasource.xml");
concentratorService =(ConcentratorService) ctx.getBean("concentratorService");
// scu.setApplicationContext(ctx);
// controllerofService =(ControllerofService) SpringContextUtil.getBean("controllerofService");
// concentratorService =(ConcentratorService) SpringContextUtil.getBean("concentratorService");
// lightPoleService =(LightPoleService) SpringContextUtil.getBean("lightPoleService");
// controllerFaultService = (ControllerFaultService) SpringContextUtil.getBean("ControllerFaultService");
}
public void run() {
try {
mServerTest = new ServerSocket(SOCKET_PORT_0);
} catch (IOException e1) {
e1.printStackTrace();
}
int size = -1;
while (true) {
try {
if (size < 0) {
System.out.println("等待前置机的链接....");
mSocket = mServerTest.accept();
System.out.println("服务器测试程序已链接....");
} else {
byte[] realBuffer = new byte[size];
System.arraycopy(buffer, 0, realBuffer, 0, size);
System.out.print("Message from front end: ");
msgList=parseFrontEndMsg(realBuffer,alist);
WebSocket.getMsgFromServer(msgList);
}
mInput = mSocket.getInputStream();
size = mInput.read(buffer);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public List<String> parseFrontEndMsg(byte[] mBytes,List<Area> alist) throws Exception{
ControllerFaultService controllerFaultService=this.controllerFaultService;
byte msg_code = mBytes[1];
String macAddr="";
switch (msg_code = mBytes[1]) {
case CONTROLLER_FAULT:
//省略代码。macAddr分析自客户端发送来的信息。
Concentrator c=concentratorService.findConcentratorByCaddress(macAddr);
//省略代码。
return faultList;
}
return null;
}
}
直接运行RunSocket的main函数,用上面这种方法service能被赋值,但是dao却是空的。
之后我又试了一中,本想spring自己注入的。
ReceiveThread:(方案二)
@Component
public class ReceiveThread extends Thread {
static final int SOCKET_PORT_0 = 8800; // 端口号
static ServerSocket mServerTest = null;
static Socket mSocket = null;
static InputStream mInput = null;
byte[] buffer;
static final byte CONTROLLER_FAULT = (byte)0x90;
List<Area> alist=new ArrayList<Area>();
List<String> msgList=new ArrayList<String>();
@Autowired
ConcentratorService concentratorService;
//@Autowired和@Resource的运行结果都一样,concentratorService为null
public void init() {
buffer = new byte[65536];
}
//以下代码同上,省略。
但是这种方法,更是什么都没有被注入,service的值为空,我不知道问题出在哪里。
是不是spring的环境在运行RunSocket的mian函数时并没有被布置?
重申一次,service和dao的配置上应该是没什么问题的,因为在Run On Server后,controller中bean都是能成功被注入并被使用。
我在看spring的入门教程,发现和我这个工程有点差别,前辈写的接口并没有setter注入或者constructor注入,但却能运行,我猜是不是用了@Autowired这些标示就可以省略前面两种方式的注入?(如果我的问题很白痴,请不要介意啊),再此先谢过各位。
“对于我这种逻辑白痴来说,spring真的很难学。”
=================ENDING==================
由于试了多种方法都没有实现service的自动注入或用容器取得service后实现dao的注入,最终还是采取了最愚蠢的方式,建立一个容器,直接取出DaoImpl的bean(而不通过service->serviceImpl->dao->daoImpl这个途径),来最终连接数据库了。
算是一种妥协吧,唉。多谢各位这么多天的热心帮助。或许之后的某一天,当自己学好spring再回来看这个问题可能就能得到更好的解决。
问题解决:https://segmentfault.com/q/10...
设置获取context线程的context为static。在thread中引用就可以了。