基于Spring的项目启动
Links
web.xml加载spring, struts2
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
spring-farmework-4.2.4 整合 struts 2.3.24.1
-
@Results( { @Result(name = ActionSupport.SUCCESS, type = "json", params = { "root", "bannerResult", "excludeNullProperties", "true", "enableGZIP", "true" }) })
-
最少所需依赖包
- spring-core-4.2.4.RELEASE.jar
- spring-web-4.2.4.RELEASE.jar
- spring-context-4.2.4.RELEASE.jar
- spring-beans-4.2.4.RELEASE.jar
- spring-aop-4.2.4.RELEASE.jar
- spring-expression-4.2.4.RELEASE.jar
- commons-logging-1.2.jar
-
整合struts 2.3.24.1
- struts2-spring-plugin-2.3.24.1.jar
- xwork-core-2.3.24.1.jar
- struts2-core-2.3.24.1.jar
- ognl-3.0.6.jar
- javassist-3.11.0.GA.jar
- commons-io-2.2.jar
- commons-fileupload-1.3.1.jar
- freemarker-2.3.22.jar
- commons-lang3-3.2.jar
- struts2-convention-plugin-2.3.24.1.jar Struts2 Annotation
- asm-3.3.jar
- struts2-json-plugin-2.3.24.1.jar Use json-default package
- asm-commons-3.3.jar 需要但有时候不报错
- struts2-config-browser-plugin-2.3.24.1.jar /config-browser/actionNames.action
-
applicationContext.xml
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring" 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/aop http://www.springframework.org/schema/aop/spring-aop-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/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd"> <context:annotation-config /> <context:component-scan base-package="" /> <task:annotation-driven /> <import resource="classpath:/applicationContext_datasource.xml" /> <ehcache:annotation-driven cache-manager="ehCacheManager" /> <bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" /> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> <property name="ignoreResourceNotFound" value="true" /> <property name="locations"> <list> <value>classpath:global.properties</value> <value>classpath:query.properties</value> </list> </property> </bean> </beans>
Spring3.2.9 整合 Hibernate4.2.2
-
spring jar
- spring-core-3.2.9.RELEASE.jar
- spring-context-3.2.9.RELEASE.jar
- spring-beans-3.2.9.RELEASE.jar
- spring-orm-3.2.9.RELEASE.jar
- spring-tx-3.2.9.RELEASE.jar
- spring-jdbc-3.2.9.RELEASE.jar
- spring-expression-3.2.9.RELEASE.jar
- spring-aop-3.2.9.RELEASE.jar
-
hibernate jar
- hibernate-core-4.2.2.Final.jar
- hibernate-commons-annotations-4.0.2.Final.jar
- hibernate-jpa-2.0-api-1.0.1.Final.jar
-
other jar
- dom4j-1.6.1.jar
- javassist-3.11.0.GA.jar
- jboss-logging-3.1.0.GA.jar
- aopalliance-1.0.jar
-
and maybe there are smoe other jars not know because they are in project already
-
applicationContext.xml
-
dataSource
<bean id="orcaleDS" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property> <property name="url" value="${xxx.url}"></property> <property name="username" value="${xxx.user}"></property> <property name="password" value="${xxx.DB.password}"></property> </bean>
-
sessionFactory
packagesToScan 需要spring3,2.5不支持<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="orcaleDS" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.format_sql">true</prop> <prop key="javax.persistence.validation.mode">none</prop> </props> </property> <property name="packagesToScan"> <list> <value>com.xxx.pojo</value> </list> </property> </bean>
-
transactionManager
@Transcation 需要annotation-driven才会生效<tx:annotation-driven/> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"> </property> </bean>
-
Junit4 and Mokito 与Spring整合
Junit4 和 Spring整合,用Spring IOC来管理Test Case,从而实现Test Case可利用Spring强大的事物管理等功能,实现Test Case对数据库操作回滚的功能,保持数据库的完整性。
Mockito能有效的mock那些测试类中的不可控的对象,比如Request和Response
注解的方式整合Spring : extends AbstractTransactionalJUnit4SpringContextTests
@ContextConfiguration(locations={
"config/applicationContext-datasource-test.xml",
"config/applicationContext-Freedom-test.xml",
"classpath:applicationContext-grid.xml",
"classpath:applicationContext-Freedom-legacy.xml"
})
实现事物回滚
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
Mockito
- MockitoAnnotations.initMocks(this);
- 使Mockito的注解生效,如果不用SpringTest跑test case,可以用@RunWith(MockitoJUnitRunner.class)代替
- @Mock 和 @InjectMocks
- @mock为一个interface提供一个虚拟的实现,成为一个mock对象。
- @InjectMocks将本test类中的mock(或@mock)注入到被标注的对象中去,也就是说被标注的对象中需要使用标注了mock(或@mock)的对象。但是被标注的对象不是一个mock对象
- @Spy:可用于实现部分mock
- @Mock的对象只有在调用了Mockito.when(obj.doSomething()).thenCallRealMethod()的时候才会调用真实方法
- 而@Spy注解的对象只有在调用了Mockito.when(obj.doSomething()).thenReturn(rtnValue)的时候才返回mock的值,但是真实方法还是会运行
- 直接返回mock后的值而运行原方法:Mockito.doReturn(true).when(obj).doSomething();
mock Request和Response
protected HttpServletResponse getReponseWithPrintWriter() throws IOException {
PrintWriter writer = org.mockito.Mockito.mock(PrintWriter.class);
HttpServletResponse response = org.mockito.Mockito.mock(HttpServletResponse.class);
org.mockito.Mockito.when(response.getWriter()).thenReturn(writer);
return response;
}
protected HttpServletResponse getReponseWithOutputStream() throws IOException {
ServletOutputStream outputStream = org.mockito.Mockito.mock(ServletOutputStream.class);
HttpServletResponse response = org.mockito.Mockito.mock(HttpServletResponse.class);
org.mockito.Mockito.when(response.getOutputStream()).thenReturn(outputStream);
return response;
}
protected HttpServletRequest getUserIdFromPortalWithMockedRequest() {
HttpServletRequest request = org.mockito.Mockito.mock(HttpServletRequest.class);
org.mockito.Mockito.when(request.getHeader("user")).thenReturn("sxq");
return request;
}
其他
- @Autowired注入Action
- System.setProperty("SERVER_ENV", "DEV");设置环境变量
Spring AOP
-
Maven dependency
- aspectjrt.jar
- aspectjtools.jar
-
@Aspect [切面]
- 一个切面包括了代理类和目标类
- 无法被扫描,需要加上@Component,或者把@Aspect加入到扫描列表中
- Aspect 类上面除了@Aspect和@Component注解外,不能添加某些其他spring annonation,比如@RefreshScope,否则会造成@Around通知的point.proceed();方法也被代理,代理方法执行两次
-
@Pointcut [切入点]
- spring的所有切入点都是方法
- execution : 声明切入点为某些方法
- pointcut="(execution * com.*.service..*.fetch(..))"
- 第1个星 : 任意返回值类型
- 第2个星 : 任意包
- 第3个星 : 任意类
- .. : 第一个点表示目录分隔,第二个点表示类
- within : 声明切入点为某些类的所有方法
- @annotation : 声明切入点为某些annonation
- Annotation需要被扫描
- bean
- spring bean的名字
-
Advice [通知]: 代理方法
- @Before/@After
- @AfterReturning
- returnning="result" : 定义返回值为参数
- @AfterThrowing
- throwing="e" : 定义异常为参数
- @Around
- this="thisBean" : 定义代理类为参数,并且也起到声明切入点的作用
- target="targetBean" : 定义目标类为参数,就是被代理类,并且也起到声明切入点的作用
- args="(arg0,arg1)" : 定义参数,并且也起到声明切入点的作用
- @Orderd(1)
- 多个通知的顺序,默认0
-
引入(Introduction)
- @DeclareParents :将代理方法实现某个接口
Spring Data JPA
Created and LastUpdated
- @CreatedDate
- @LastModifiedDate
- @EnableJpaAuditing
Spring JPA 乐观锁
- @Version
- 必须是javax.persistence包下的
- 数据类型是Long, Postgresql里是bigint
- 不支持Update操作,只能save entity
去除save方法的select
- select的作用
- 用于判断是否已经存在唯一约束,如果存在update,否则执行inster
- 用于JPA乐观锁 去除后自己判断乐观锁,单需要与update做成一个事务从而增加性能
- 去除select
- class InboundRequest : Persistable
- override fun getId(): String? = inboundRequestId
- override fun isNew(): Boolean = true
- class InboundRequest : Persistable
其他
- 对JPA规范的封装,可以使用Hibernate的JPA实现,还可以切换到其他JPA实现
- public interface BondLevelsLiveRepository extends JpaRepository < BondLevelsLivePojo, BondLevelsLivePojoId >
- @Modifying : 完成修改操作(注意:不支持新增)
- @Query("delete from BondLevelsLivePojo pojo where pojo.lastUpdated < :date")
- void deleteStaleEntities(@Param("date") Date date);
- 在不同package下的repo,entity
- @EnableJpaRepositories(basePackages = ["org.springframework.statemachine.data.jpa"])
- @EntityScan(basePackages = ["org.springframework.statemachine.data.jpa"])
Spring Scheduler
-
@Scheduled与@Async合用的时候,不管前一个任务又没有完成,都会再起一个线程开始新的任务
-
@Scheduled默认单线程,可以通过设置线程池的个数来达到多现成的需求
@Configuration public class SchedulerConfiguration implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); taskScheduler.setPoolSize(20); taskScheduler.initialize(); taskRegistrar.setTaskScheduler(taskScheduler); } }
Spring Cache
Getting Start
- Maven dependency
- org.springframework.boot : spring-boot-starter-cache
- spring-context-x.RELEASE.jar
- org.springframework.boot : spring-boot-starter-cache
- @EnableCaching
- 可以放在spring boot 启动类
- 启用@Cacheable, @CachePut and @CacheEvict
- doc : https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache
- CacheManager
- 不指定CacheManager实现的时候默认使用ConcurrentHashMap
Spring MVC
常用Annonation
- @RestController或者使用@Controller+@ResponseBody
- @RequestMapping(value = "/springboot/webapi/price/get", method = RequestMethod.GET)
- PostMapping/GetMapping
- consumes: 限制接受请求的数据类型(Content-Type),MediaType
- produces: 限制返回的数据类型(accept)
- @PathVariable
- 一般把key放在请求的path里{key}
@RequestParam(required=false) String ccy
@ModelAttribute - 默认,可以忽略不写
- 自动寻找path/param里的参数
@ResponseStatus - 定义返回的状态码
@ControllerAdvice - @ExceptionHandler: 相关的Controller的特定Exception会被拦截,又切面同一处理
- 一般把key放在请求的path里{key}
- ModelMap可以用于返回多个stiring
9种Http Method
- GET : 获取
- POST : 添加
- PUT/PATCH : 修改/部分修改
- DELETE : 删除
- OPTIONS : 获取可用的协议有哪些
- HEAD : 只获取head
- CONNECT : 维护一次心跳
- TRACE : 跟踪
Reactive 非阻塞式编程
- Spring MVC 使用java nio实现
- 直接释放请求链接,等到结果完成后返回Response响应
- DeferredResult
: 返回单个对象 - ResponseBodyEmitter : 返回一个列表
- SseEmitter : 支持持续响应Response
- DeferredResult
- Spring Web Flex也支持这种操作
- Spring 很多框架支持Reactive编程,比如Redis等
- Reactive 编程与java流一起使用
RestTemplate
基础
- GET
- getForEntity("http://rates-cache//subject/{1}/{2}/get", String.class, "bond", "key")
- getForObject : 等同于entity.getBody()
- POST
- postForEntity("http://rates-cache//subject/{1}/put?param={2}", subjects, void.class, "bond", "param");
- postForObject
- postForLocaltion : 用于提交资源,返回新资源的URI
- PUT
- put("http://rates-cache//subject/{1}/put", subjects, "bond"); : 返回void
- DELETE
- delete("http://rates-cache//subject/{1}/put", "bond"); : 返回void
Request Header
val httpHeaders = HttpHeaders()
httpHeaders.contentType = MediaType.APPLICATION_JSON
httpHeaders.setBasicAuth("usr","pwd")
httpHeaders.accept = listOf(MediaType.ALL) // 接受任何形式的返回值类型
val httpEntity = HttpEntity(request, httpHeaders)
val response = restTemplate.postForObject(url, httpEntity, String::class.java)
Spring Annonation
- @ConditionalOnMissingBean
- 注解里的参数的类型如果已经存在一个Bean,那么被此注解修饰的类的方法上面有此注解的方法将不再执行
- @ConfigurationProperties
- 将properties或者yml配置直接转成对象
- 自定义的配置,对象可以自定义
- spring为很多模块提供了对象
- spring cloud zuul : ZuulProperties
Spring Integration Test
- 限定profile和指定profile
- @ActiveProfiles("integration-mock")
- @Profile("integration-mock")
- 使用随机端口启动服务,并发送http请求进行集成测试
- @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
- @Autowired var testRestTemplate: TestRestTemplate? = null
- EmbeddedDatabase
- @AutoConfigureEmbeddedDatabase
- testImplementation("io.zonky.test:embedded-database-spring-test:1.5.0")
- EmbeddedKafka
- @EmbeddedKafka(partitions = 1, topics = [PAYMENT_CORE_EVENT_TOPIC])
- testImplementation("org.springframework.kafka:spring-kafka-test")
- spring.cloud.stream.kafka.binder.brokers.kafka=9092
Spring statusmachine
-
machine id
- 一个订单一个machine id
- 一个machine id一条记录
- UUID: 属于同一个state machine
factory与service创建StateMachine对比
- factory
- 自动持久化
- 不会缓存state machine
- 自动读取数据库
- service
- 自动持久化
- 会缓存state machine, 所以需要在complate时候release
- 自动读取数据库 : autoStart = false and acquireStateMachine: start=false