解决方案 »

  1.   

    你是WEB系统不是桌面系统,WEB系统存在离线一说么。你难道要在每个客服的PC上装一个tomcat和JDK,这科学么。叫你们BOSS换成桌面应用系统可以考滤一下离线。然后用你这套思路来实现。
      

  2.   


    如果要把Tomcat部署到客户本机的话,我想一小时从服务器抓取一次数据比较合适吧?隔一天是不是有点久了 。。
      

  3.   


    现在就是有这么一个需求,我们的系统在网上供客户访问,客户搞个需求想在断网的时候也可以进行一些重要的操作,所以只能针对现在项目想些解决方案了。客户端也考虑过,试着用javaFX做了几个模型,发现些问题:1是太难看了,2 是javaFX网上资料太少,周期短的基础上进行深度开发不太现实。。所以又把注意力转到Web上了
      

  4.   


    如果要把Tomcat部署到客户本机的话,我想一小时从服务器抓取一次数据比较合适吧?隔一天是不是有点久了 。。这个时间根据你的业务需求看吧,因为我们的数据量有点大,一个小时都跑步完的,而且白天跑的时候对系统存在一定压力,所以一般都是半夜跑,这个请根据你的实际情况分析,呵呵
      

  5.   

    想多了吧,你见过web还能离线?web的意思就是东西都在服务器上,客户端只有一个浏览器而已,这种怎么离线,赶快停止你老板稀奇的设想,不然你下一步就是要开发一个pc客户端了。
      

  6.   

    你可以考虑用tomcat mini+derby+jre打包成客户端,然后在主系统做个模块:
    1、上传用户安装路径
    2、操作离线功能的启动和停止(运行bat或者exe 启动服务)
    3、数据同步,数据可以同步一次删除一次旧数据(用户可以手动同步和自动同步数据)
    还有是否所有功能都需要离线的问题。
      

  7.   

    WEB是不能离线的,转移也没用。不过我倒想到一种用C+JS+HTML。用HTML与JS做一个界面,然后用C写一个应用框架,主要功能是读取本地文件与保存文件等,并提供给JS调用的API,用JS调用C来完成文件的存储与修改等,在离线时就可以用这一套。在线时就把本地文件与线上的数据库同步。写好之后也像一个伪桌面应用程序了,直接把客户端发给客户。
      

  8.   

    apache mina项目提供了http/ftp/xmpp服务,而derby数据库最适合小型的数据存储,你只要把项目部分功能放在mina项目目录中,然后web控制启动就可以达到一个小型服务器的效果了。
      

  9.   


    如果要把Tomcat部署到客户本机的话,我想一小时从服务器抓取一次数据比较合适吧?隔一天是不是有点久了 。。这个时间根据你的业务需求看吧,因为我们的数据量有点大,一个小时都跑步完的,而且白天跑的时候对系统存在一定压力,所以一般都是半夜跑,这个请根据你的实际情况分析,呵呵那没办法了,我们情况还比较特殊。如果部署也只是在客户的电脑上安装一个Tomcat配置应用程序。只能白天定时跑,晚上客户就关机回家了 。。 
      

  10.   

    嗯,你说的这个是需要我把本地版本开发完成后,把WEB打包安装的内容吧?现在考虑还有点早 ~
      

  11.   

    数据问题你可以做个线程把主数据库的数据抽取部分要用的导入到用户那边(可以客户手动与自动),线程加个判断能否连接用户PC,如果可以则提取数据到主数据库表里,表不需要变啊,copy一份到客户端就行了。
      

  12.   

    我现在遇到一个问题,就是以目前的需求情况我需要在项目中配置两个数据源(本地、远程)在同步的时候切换,我现在使用Spring的方式,继承AbstractRoutingDataSource类完成在代码上手动切换。private boolean doBaseCompany() {
    if (!Boolean.valueOf(prop.get("BaseCompany").toString()))
    return true;
    DBContextHolder.setCustomerType(DBContextHolder.DATASOURCE_LOCAL); // 切换数据源到本地
    SysRole role = new SysRole();
    role.setCompanyId("lindp1");
    role.setRoleName("lindp1");
    sysRoleDao.addSysRole(role); DBContextHolder.setCustomerType(DBContextHolder.DATASOURCE_REMOTE); // 切换数据源到远程
    SysRole role2 = new SysRole();
    role2.setCompanyId("lindp2");
    role2.setRoleName("lindp2");
    sysRoleDao.addSysRole(role2);
    return true;
    }
    就是通过上面代码实现数据库切换,可是我添加的时候定时器第一次执行只会给远程数据库添加两条(lindp1、lindp2)的数据,本地数据库根本没操作。不知道是不是事务的问题?是不是要配置分布式事务啊?
      

  13.   

    你参考下http://blog.csdn.net/shuai825644975/article/details/17021181 
      

  14.   

    对,我就是使用这种方式配置的多数据源。我的事务不起作用,家了@Transactional注解后第一次加载数据源无效,使用的是默认数据源 。。
      

  15.   

    你调用第二个数据源前执行了线程的remove()以及commit事务了吗?
      

  16.   


    我就没用线程,一直在使用定时器。
    我在项目中配置了atomikos分布式事务,网上说spring在一个事务中不支持多数据源切换。
    我现在就做不下去了 。。
      

  17.   

    你参考下JBOSS XA数据源
    standalone.xml<datasources>
        <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
            <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
            <driver>h2</driver>
            <security>
                <user-name>sa</user-name>
                <password>sa</password>
            </security>
        </datasource>
        <xa-datasource jta="true" jndi-name="java:jboss/datasources/MYDB_ONE" pool-name="MYDB_ONE" enabled="true" use-java-context="true" use-ccm="true">
            <xa-datasource-property name="ServerName">
                localhost
            </xa-datasource-property>
            <xa-datasource-property name="DatabaseName">
                MYDB_ONE
            </xa-datasource-property>
            <xa-datasource-property name="SelectMethod">
                cursor
            </xa-datasource-property>
            <xa-datasource-class>com.microsoft.sqlserver.jdbc.SQLServerXADataSource</xa-datasource-class>
            <driver>sqljdbc</driver>
            <xa-pool>
                <is-same-rm-override>false</is-same-rm-override>
            </xa-pool>
            <security>
                <user-name>some_user</user-name>
                <password>some_password</password>
            </security>
            <validation>
                <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mssql.MSSQLValidConnectionChecker"/>
            </validation>
        </xa-datasource>
        <xa-datasource jta="true" jndi-name="java:jboss/datasources/MYDB_TWO" pool-name="MYDB_TWO" enabled="true" use-java-context="true" use-ccm="true">
            <xa-datasource-property name="ServerName">
                localhost
            </xa-datasource-property>
            <xa-datasource-property name="DatabaseName">
                MYDB_TWO
            </xa-datasource-property>
            <xa-datasource-property name="SelectMethod">
                cursor
            </xa-datasource-property>
            <xa-datasource-class>com.microsoft.sqlserver.jdbc.SQLServerXADataSource</xa-datasource-class>
            <driver>sqljdbc</driver>
            <xa-pool>
                <is-same-rm-override>false</is-same-rm-override>
            </xa-pool>
            <security>
                <user-name>some_user</user-name>
                <password>some_password</password>
            </security>
            <validation>
                <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mssql.MSSQLValidConnectionChecker"/>
            </validation>
        </xa-datasource>
        <drivers>
            <driver name="h2" module="com.h2database.h2">
                <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
            </driver>
            <driver name="sqljdbc" module="com.microsoft.sqlserver.jdbc">
                <driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class>
            </driver>
            <driver name="postgresql" module="org.postgresql">
                <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
            </driver>
        </drivers>
    </datasources>springJpaConfig.xml<!-- Use @PersistenceContext annotations for injecting entity managers -->
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /><!-- Set up JTA transaction manager -->
    <tx:jta-transaction-manager /><bean id="entityManagerFactoryMyDB" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="MyDB" />
        <property name="dataSource" ref="dataSourceMyDB" />
        <property name="packagesToScan" value="my.package.with.jpa.entities" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
            </bean>
        </property>
        <property name="jpaPropertyMap">
            <map>
                <entry key="javax.persistence.transactionType" value="jta" />            <entry key="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
                <entry key="jboss.entity.manager.factory.jndi.name" value="java:app/MyDBEntityManagerFactory" />            <entry key="hibernate.dialect" value="org.hibernate.dialect.SQLServer2008Dialect" />
            </map>
        </property>
    </bean><bean id="dataSourceMyDB" class="some.package.AbstractRoutingDataSourceMyDB">
        <property name="lenientFallback" value="false" />
        <property name="defaultTargetDataSource" value="java:jboss/datasources/ExampleDS" />
        <property name="targetDataSources">
            <map key-type="String">
                <!-- This is a placeholder that will be filled in by BeanFactoryPostProcessor -->
            </map>
        </property>
    </bean><!-- This allows us to modify Spring configuration load the list of datasources -->
    <bean class="some.package.DatasourceRegisteringBeanFactoryPostProcessor" />DatasourceRegisteringBeanFactoryPostProcessor.javapackage some.package
    class DatasourceRegisteringBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
            HashMap<String, String> connectionsListMyDB = new HashMap<>();        // Load your connection list from wherever you need to, you can
            // enumerate them directly from JNDI or some configuration location
            connectionsListMyDB.put("db1", "java:jboss/datasources/MYDB_ONE");
            connectionsListMyDB.put("db2", "java:jboss/datasources/MYDB_TWO");        if (connectionsList.isEmpty())
                throw new RuntimeException("No JPA connections defined");        // Configure the dataSource bean properties
            BeanDefinitionRegistry factory = (BeanDefinitionRegistry) beanFactory;
            MutablePropertyValues mpv = factory.getBeanDefinition("dataSourceMyDB").getPropertyValues();        ManagedMap<String, String> mm = (ManagedMap<String, String>) mpv.getPropertyValue(
                    "targetDataSources").getValue();
            mm.clear();
            for (Entry<String, String> e : connectionsListMyDB.entrySet()) {
                mm.put(e.getKey(), e.getValue());
            }
        }
    }AbstractRoutingDataSourceMyDB.java
    public class AbstractRoutingDataSourceMyDB extends AbstractRoutingDataSource {
        @Override
        protected Object determineCurrentLookupKey() {
            return getDbConnectionMyDB();
        }    // ThreadLocal variable so that the connection gets set for the current thread
        // using spring's request scope on the class instead of ThreadLocal would also work here.
        private final ThreadLocal<String> contextHolder = new ThreadLocal<String>();    public void setDbConnectionMyDB(String myKey) {
            Assert.notNull(myKey, "myKey cannot be null");        contextHolder.set(myKey);        String k = contextHolder.get();
        }    public String getDbConnectionMyDB() {
            return (String) contextHolder.get();
        }    public void clearDbConnectionMyDB() {
            contextHolder.remove();
        }
    }SomeTableDAO.java@PersistenceContext(unitName = "MyDB")
    private EntityManager em;@Autowired
    private AbstractRoutingDataSourceMyDB routingSource;public void someMethod(int id) {
        em.flush();
        em.clear();
        routingSource.setDbConnectionMyDB("db1");
        em.remove(em.getReference(Something.class, id)); // delete something in db1    em.flush();
        em.clear();
        routingSource.setDbConnectionMyDB("db2");
        em.remove(em.getReference(Something.class, id)); // delete something else with the same id in db2
    }