第二期

开发问题及解决方案【190125】

2019/01/25

问题列表

序号分类问题备注
1IBM MQ配置用户名密码已解决
2SqlServer查询条件忽略大小写已解决
3配置多数据源使用mybatis配置多个数据源已解决
4js date在js中实现时间的格式化已解决
5@ComponentSSM中出现使用@Component的同名类已解决
6JSONJSONArray和JSONObject只能解析对应形式已解决
7POSTpost参数的传入方式已解决
8SqlServer查询多条数据,拼成一条已解决
9SqlServer如何关联两个数据库的表已解决
10QuartzSpring整合quertz的配置已解决

解决方案

1.1 IBM MQ配置信息如下
<?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:context="http://www.springframework.org/schema/context" 
		xmlns:jms="http://www.springframework.org/schema/jms"
		xsi:schemaLocation="
			http://www.springframework.org/schema/beans
			http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
			http://www.springframework.org/schema/context
			http://www.springframework.org/schema/context/spring-context-4.0.xsd
			http://www.springframework.org/schema/jms
			http://www.springframework.org/schema/jms/spring-jms-4.0.xsd">

	<bean id="connectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
		<property name="transportType" value="1"/>
		<property name="queueManager" value="********"/>
		<property name="hostName" value="*****************"/>
		<property name="port" value="*******"/>
		<property name="channel" value="*******"/>
		<property name="CCSID" value="1381"/>
	</bean>
	
    <bean id="myConnectionFactory" 
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
        <property name="username" value="mqm"/>
        <property name="password" value="Password1$"/>
        <property name="targetConnectionFactory" ref="connectionFactory"/>
    </bean>
    
	<bean id="queueDes" class="com.ibm.mq.jms.MQQueue">
		<property name="baseQueueManagerName" value="INT_NB"/>
		<property name="baseQueueName" value="NB_QUENE"/>
	</bean>

	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="myConnectionFactory"/>
		<property name="defaultDestination" ref="queueDes"/>
		<property name="pubSubDomain" value="false"/>		<!-- 队列 -->
	</bean>

	<!-- 2.监听器 -->
	<bean id="msgListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
		<property name="delegate">
			<bean class="com.sinosoft.uwca.listener.mq.MsgReceiver"/>
		</property>
	</bean>
	<bean id="container" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
		<property name="connectionFactory" ref="myConnectionFactory"/>
		<property name="destination" ref="queueDes"/>
		<property name="messageListener" ref="msgListener"/>
	</bean>

</beans>

UserCredentialsConnectionFactoryAdapter 提供获取消息时的用户验证。


2.1 使用upper lower

条件与值均为大写或均为小写。

select * from tablename where lower(condition) = 'value';
select * from tablename where upper(condition) = 'VALUE';

3.1 使用自定义函数

jndi配置数据源

  • 在web.xml中需要配置resource-ref, 并使用res-ref-name关联
  <resource-ref>   
         <res-ref-name>jdbc/prm</res-ref-name>   
         <res-type>javax.sql.DataSource</res-type>   
         <res-auth>Container</res-auth>   
         <res-sharing-scope>Shareable</res-sharing-scope>   
  </resource-ref>
  <resource-ref>   
         <res-ref-name>jdbc/prmods</res-ref-name>   
         <res-type>javax.sql.DataSource</res-type>   
         <res-auth>Container</res-auth>   
         <res-sharing-scope>Shareable</res-sharing-scope>   
  </resource-ref>
  • 配置数据源注意web.xml中的res-ref-name就是指的name对应的值
  <Context>
    <Resource auth="Container" driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" 
      initialSize="5" maxActive="120" maxIdle="5" maxWait="5000" name="jdbc/prm"
      password="Devs123$" type="javax.sql.DataSource" url="jdbc:sqlserver://10.164.27.37:1433;DatabaseName=NB-Workflow" 
      username="NBWorkflowadmin" />
    <Resource auth="Container" driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" 
      initialSize="5" maxActive="120" maxIdle="5" maxWait="5000" name="jdbc/prmods"
      password="Devs123$" type="javax.sql.DataSource" url="jdbc:sqlserver://10.164.27.37:1433;DatabaseName=NB-Middle" 
      username="NBWorkflowadmin" />
  </Context>

  • 配置mybatis映射 需要注意jndiName也需要与上面SQLServerDriver的name对应
  <!-- 加载配置信息1 -->
	<bean id="messageSource"
		class="org.springframework.context.support.ResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<value>config</value>
			</list>
		</property>
	</bean>
	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"
		scope="singleton">
		<property name="jndiName" value="java:comp/env/jdbc/prm" />
		<property name="resourceRef" value="true" />
	</bean>
	
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="mapperLocations" value="classpath:mappers/**/*.xml" />
	</bean>

	<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory" />
		<constructor-arg index="1" value="BATCH" />
	</bean>

	<!-- uw语句映射器:自动扫描 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.sinosoft.uwca.persistence" />
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
	</bean>


	<!-- 加载配置信息2 -->
	<bean id="messageSourceMiddle"
		class="org.springframework.context.support.ResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<value>config</value>
			</list>
		</property>
	</bean>
	<bean id="dataSourceMiddle" class="org.springframework.jndi.JndiObjectFactoryBean"
		scope="singleton">
		<property name="jndiName" value="java:comp/env/jdbc/prmods" />
		<property name="resourceRef" value="true" />
	</bean>
	
	<bean id="sqlSessionFactoryMiddle" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSourceMiddle" />
		<property name="mapperLocations" value="classpath:mapperods/**/*.xml" />
	</bean>

	<bean id="sqlSessionMiddle" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactoryMiddle" />
		<constructor-arg index="1" value="BATCH" />
	</bean>

	<!-- uw语句映射器:自动扫描 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.sinosoft.uwca.mapperods" />
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryMiddle" />
	</bean>

  • 最后上面用到的config其实查找的是config目录下的mybatis配置文件
  <?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>
    <settings>
      <setting name="cacheEnabled" value="true" />
      <setting name="lazyLoadingEnabled" value="true" />
      <setting name="multipleResultSetsEnabled" value="true" />
      <setting name="useColumnLabel" value="true" />
      <setting name="useGeneratedKeys" value="false" />
      <setting name="defaultExecutorType" value="SIMPLE" />
      <setting name="defaultStatementTimeout" value="100" />
      <setting name="safeRowBoundsEnabled" value="false" />
      <setting name="mapUnderscoreToCamelCase" value="false" />
      <setting name="localCacheScope" value="SESSION" />
      <setting name="jdbcTypeForNull" value="OTHER" />
      <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString" />
    </settings>
  </configuration>

4.1 使用自定义函数
// 时间格式化 pattern 为日期格式
function SimpleDateFormat(pattern){
	var fmt = {};
	fmt.pattern = pattern;
	
	fmt.parse = function(source){
		try{
			return new Date(source);
		}catch(e){
			return null;
		}
	};
	
	fmt.format = function(date){
		if(date === undefined || date == null || date===""){
			return "";
		}
		
		try{
			date = new Date(date);
		}catch(e){
			return "";
		}
		
		var strTime = this.pattern;//时间表达式的正则
		
    var o = {
            "M+": date.getMonth() + 1,  //月份 
            "d+": date.getDate(),       //日 
            "H+": date.getHours(),      //小时 
            "m+": date.getMinutes(),    //分 
            "s+": date.getSeconds(),    //秒 
            "q+": Math.floor((date.getMonth() + 3) / 3), //季度 
            "S": date.getMilliseconds() //毫秒 
        };
    
    if (/(y+)/.test(strTime)){
      strTime = strTime
        .replace(RegExp.$1, (date.getFullYear() + "")
        .substr(4 - RegExp.$1.length));
    } 
    for (var k in o){
      if(o.hasOwnProperty(k)){
        if (new RegExp("(" + k + ")").test(strTime)){
          strTime = strTime.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));	
        }
      }
    }
    return strTime;
	};
	return fmt;
}

5.1 需要使用不同的name进行区分
@Component
public class Man {
    ......
}

Spring不能区分不同包下的同名类,因此产生bean时会产生同名的bean,项目启动是会有Annotation-specified bean name...错误,需要设置一个不同于默认值(此处为man)的value即可

@Component("mansec")
public class Man {
    ......
}

6.1 统一使用JSONArray解析

一般出现在XML转JSON之后解析

比如<a>节点在xml格式的报文中出现了次数可能为1次或多次,当使用工具类转换时,就会产生两种JSON报文,而这两种报文又只能分别使用JSONObject和JSONArray进行解析。

为了兼容,可以将JSONObject封装到JSONArray中,如下:

private JSONArray convertJSONArray(JSONObject jsonParentObj, String str) {
    JSONArray jsonArray = jsonParentObj.optJSONArray(str);
    JSONObject jsonObject = jsonParentObj.optJSONObject(str);
    if(jsonObject != null && jsonArray == null) {
        jsonArray = new JSONArray();
        jsonArray.put(jsonObject);
    }
    return jsonArray;
}

7.1 传入Map类型
@RequestMapping(value = "/CalPrem" , method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
@ResponseBody
public Object CalPrem(@RequestParam Map<String,Object> map, HttpServletRequest request) throws InterruptedException {
	......................
}


7.2 传入String类型 一般为json字符串
@RequestMapping(value="/updatePolicy", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
@ResponseBody
public String updatePolicyStatus(@RequestBody String requestString) throws JSONException {
	........
}

8.1 使用 stuff 和 for xml path

当查询结果出现多条数据时。如果想使其以","分割或者其他符号分割,拼装成一条数据。可以使用下面的方法:

select stuff((select ','+clntpf.SURNAME from UW_NB_LA_CLNTPF_ODS clntpf where clntpf.CLNTNUM
 in (select lifepf.LIFCNUM from UW_NB_LA_LIFEPF_ODS lifepf where lifepf.CHDRNUM = '41592420' ) for xml path('')), 1, 1, '')

这里使用了stuff(src, addr, len, str),效果为将字符串src从addr位置开始将len长度的字符替换为str。
for xml path(var)效果是将多条查询结果拼成以var为标签的xml报文。当var为’'时,效果为字符串而非xml。
如下:

select ','+ lifepf.LIFCNUM from UW_NB_LA_LIFEPF_ODS lifepf where lifepf.CHDRNUM = '41592420' for xml path('')
--结果:,74427921,74427921,74427916,74427916
select ','+ lifepf.LIFCNUM from UW_NB_LA_LIFEPF_ODS lifepf where lifepf.CHDRNUM = '41592420' for xml path('body')
--结果:<body>,74427921</body><body>,74427921</body><body>,74427916</body><body>,74427916</body>
select ','+ lifepf.LIFCNUM from UW_NB_LA_LIFEPF_ODS lifepf where lifepf.CHDRNUM = '41592420' for xml path
--结果:<row>,74427921</row><row>,74427921</row><row>,74427916</row><row>,74427916</row>

9.1 使用…

有这个问题其实还是对基础的数据库表访问不清楚。

--访问数据库的方法
select * from [database-table]..studentinfo;

10.1 常见配置

为了年前能出这一期,这个问题其实是凑得。我有罪~其实也方便自己拷贝。

  • 配置任务

    <!-- 短信批处理 -->
    <bean id="autoSendSMSJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject">
            <ref bean="tAutoSmsServiceI" />
        </property>
        <property name="targetMethod">
            <value>sendSmsMessage</value>
        </property>
        <!-- 指定concurrent属性,false表示非并发执行 -->
        <property name="concurrent">
            <value>false</value>
        </property>
    </bean>
    
  • 触发器

    <bean id="autoSendSmsTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">       
            <property name="jobDetail">
                <ref bean="autoSendSMSJob" />
            </property>
            <property name="cronExpression">
                <!-- 每隔五分钟整时发送 -->
                <value>0 0/5 * * * ?</value>
            </property>
        </bean>
    
  • 调度器

    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    		<!-- 添加触发器 -->
    		<property name="triggers">
    			<list>
    				<ref bean="autoSendSmsTrigger" />
    			</list>
    		</property>
    	</bean>
    

基础知识可以参考下面的链接:

https://www.cnblogs.com/zhenyuyaodidiao/p/4755649.html


备注

Nikola Zhang: 3.1继续扩展到不同数据库系统, 不同架构


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值