0%

spring websocket 配置样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
@EnableWebSocketMessageBroker //启用 websocket
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/websocket") // 配置 websocket 连接端点
.withSockJS(); // 启用 sockJs 支持
}

@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/rs/dm/topic"); // 设置 向客户端发送消息的前缀,不满足该前缀的目的地会被过滤掉。
}
}

spring 请求过程

第一步

请求离开浏览器,携带用户请求的信息前往 DispatcherServlet

第二步

DispatcherServlet 是一个前端控制器,任务是将请求发送给指定的 controller 方法。
因此 DispatcherServlet 需要通过查询 处理器映射 来确定请求的下一站是什么。

第三步

通过 处理器映射 确定好目的地后,DispatcherServlet 会将请求发送给指定的控制器

第四步

控制器在完成逻辑处理后,通常会产生一些信息(model)。之后,将 产生的model 和 指定的视图名 一起发回给 DispatcherServlet。

第五步

DispatcherServlet 通过视图解析器(view resolver)将 逻辑视图名 匹配为一个特定的视图实现。

第六步

DispatcherServlet 将模型数据交付给视图,渲染出最后的结果。

第七步

通过响应对象将 最终的渲染结果传递到客户端。

spring MVC 基本环境搭建

详见 《spring实战》章节5.1.2

环境与profile

Profile注解

单独使用时: 作用于类名,指定该类属于哪一个profile环境
@bean一起: 作用于方法,指定该bean属于哪一个profile环境

激活profile

设置 属性 spring.profiles.active。

  • 作为DispatcherServlet的初始化参数;
  • 作为Web应用的上下文参数;
  • 作为JNDI条目;
  • 作为环境变量;
  • 作为JVM的系统属性;
  • 在集成测试类上,使用@ActiveProfiles注解设置。

条件化bean

@Conditional 注解: 作用于类名上,与 Condition接口 配合。
Condition 接口: 只有一个 matches方法,只有在该方法返回 true 时才会创建带有@Conditional的bean。

通过这两个注解和接口的配合,可以下面措施来决定是否创建 被注解的bean。

  • 检查环境变量是否存在指定的值
  • 检查指定的bean是否存在
  • 检查指定的资源是否存在
  • 等等

样例 Profile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {

/**
* The set of profiles for which the annotated component should be registered.
*/
String[] value();

}


class ProfileCondition implements Condition {

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
if (context.getEnvironment() != null) {
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
for (Object value : attrs.get("value")) {
if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
return true;
}
}
return false;
}
}
return true;
}

}

##自动装配歧义性

  • @Primary, 与@bean或者@Component组合: 将有该注解的bean设为首选项
  • @Qualifier, 与@Autowired组合: 指定注入哪个bean
  • @Qualifier, 与@Component@Bean组合: 指定该bean生产的beanId

##bean的作用域

@Scope注解 与@Component@Bean组合,表明bean的作用域。

其有以下四种值:

  • 单例(Singleton):在整个应用中,只创建bean的一个实例。
  • 原型(Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
  • 会话(Session):在Web应用中,为每个会话创建一个bean实例。 使用场景: 购物车等
  • 请求(Rquest):在Web应用中,为每个请求创建一个bean实例。

请求域和会话域的详细介绍 参见《spring实战》章节3.4.1 。

运行时值注入

引入外部值

  1. Value注解: 可以使用 属性占位符或者SpEL表达式。
  2. Environment 对象: 获取环境变量和判断运行profile
1
2
3
4
5
6
7
8
9
public class Ad{

@Value("${a.c.v}")
private String aaa;

@Autowired
Environment environment;

}

SpEL

  • 使用bean的ID来引用bean;
  • 调用方法和访问对象的属性;
  • 对值进行算术、关系和逻辑运算;
  • 正则表达式匹配;
  • 集合操作。

属性占位符需要放到 “${ … }”之中
SpEL表达式需要放到 “#{ … }”中

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 调用普通类的方法
#{T{System}.currentTimeMillis()}

-- 获取 指定bean的字段信息
#{beanId.field}

-- 调用 指定bean的方法
#{beanId.method()}

-- 引用系统属性
#{systemProperties['aa.aa']}

-- 避免空指针,中间过程出现null,表达式结果返回null
#{beanId.select()?.dosome()}

自动装配bean

  • @Component 放在类名上: 表明该类为 一个spring 组件类。
  • @ComponentScan 放在类名上: 开启扫描功能, spring 会去扫描指定 包名 或者 类名 的 java 配置类。
  • @Autowired 放在字段或者方法上: 从应用上下文中,找到符合条件的类实例A,将该实例A与被注解的变量绑定。

配置类

当引用第三方jar时,是无法在需要的类上加 @Component 注解的,因此 需要使用另一种方法: 配置类。

  • @Configuration 放在类名上: 表明该类为配置类,该类包含各种 bean 实例
  • @Bean 放在方法上: 表明 该方法的返回对象 为一个 bean 实例,该实例会被注册到spring应用上下文中。
  • @Import 放在类名上: 将 @Importvalue属性指定的普通类或者配置类加载到当前应用上下文中。

需要注意的是 当调用 @Bean 注解的方法,spring会拦截该方法的调用,返回该方法创建的bean,而不是创建新的对象。

通过 XML 装配

由于通过注解形式基本能代替xml方式。这里就不介绍了。

简化java开发

DI 依赖注入

使 相互协作的类 保持松散耦合。

AOP

允许开发者将 遍布应用各处的功能 统一分离出来,整合成可重用的类。如 日志、事务管理和安全等服务

模板代码

通过封装 jdbc 等 样板代码,利用 JdbcTemplate 等 减少 样板代码的重复量。

spring的bean

spring的bean是由spring的容器管理的。

spring的容器主要分为两大类:

  • bean工厂: 最简单的容器提供基本的DI支持
  • 应用上下文: 基于 beanFactory 构建。提供更高级别的服务。

最基本的 ApplicationContext 接口

  • getId()
  • getApplicationName()
  • getDisplayName()
  • getStartupDate()
  • getParent()
  • getAutowireCapableBeanFactory()

最基本的 beanFactory 接口

  • getBean()
  • containsBean()
  • isSingleton()
  • isPrototype()
  • isTypeMatch()
  • 等等

下面主要介绍 应用上下文。

spring应用上下文(Application Context)

该类用于 装载bean 的定义并将他们组装起来。

spring应用上下文有多种实现:

  • AnnotationConfigApplicationContext 加载基于Java配置类
  • AnnotationConfigWebApplicationContext 加载基于Java配置类
  • FileSystemXmlApplicationContext 加载位于文件系统路径下的一个或者多个XML配置文件
  • ClassPathXmlApplicationContext 加载位于应用程序类路径下的一个或者多个XML配置文件。
  • XmlWebApplicationContext 加载web应用下的一个或者多个XML配置文件

WebApplicationContext 后缀的应用上下文,主要用于Web应用。会在之后详细讲解。

bean 的生命周期

  1. spring 对 bean 进行实例化
  2. spring 将 值 和 bean 的引用注入到 bean 对应的属性中
  3. 若 bean 实现了 BeanNameAware 接口,spring 将 bean 的 Id 传递给 setBeanName() 方法
  4. 若 bean 实现了 BeanFactoryAware 接口,spring 将调用 setBeanFactory() 方法,将 BeanFactory 容器实例传入
  5. 若 bean 实现了 ApplicationContextAware 接口,Spring 将调用 setApplicationContext()方法,将 bean 所在的应用上下文的引用传入进来;
  6. 若 bean 实现了 BeanPostProcessor 接口,Spring将调用它们的 postProcessBeforeInitialization() 方法;
  7. 若 bean 实现了 InitializingBean 接口,Spring将调用它们的 after-PropertiesSet()方法。类似地,如果 bean 使用init-method声明了初始化方法,该方法也会被调用;
  8. 若 bean 实现了 BeanPostProcessor 接口,Spring将调用它们的 postProcessAfterInitialization() 方法;
  9. 若 bean 已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁;
  10. 若 bean 实现了 DisposableBean 接口,Spring 将调用它的 destroy() 接口方法。同样,如果bean 使用destroy-method声明了销毁方法,该方法也会被调用。

spring 模块

具体介绍 阅读 <<spring实战>>。

查看 oracle 相关信息

查看 NLS 相关信息

数据库级别

select * from nls_database_parameters;

会话级别

select * from nls_session_parameters;

查看版本信息

select * from v$version;

查看数据库字符集

SELECT userenv(‘language’) FROM dual;

中文排序

中文排序选项

  • SCHINESE_RADICAL_M 按照部首(第一顺序)、笔划(第二顺序)排序
  • SCHINESE_STROKE_M 按照笔划(第一顺序)、部首(第二顺序)排序
  • SCHINESE_PINYIN_M 按照拼音排序

设置排序方式

  1. 当前会话级别

alter session set nls_sort = SCHINESE_PINYIN_M;

  1. 语句级别

select * from dept order by nlssort(name,’NLS_SORT=SCHINESE_PINYIN_M’);

  1. 系统级别(在数据库端设置)

set NLS_SORT=SCHINESE_PINYIN_M ;

  1. 设置环境变量(网上有这种说法,但是并不生效)

-Duser.language=zh -Duser.region=CN -Duser.country=CN

  1. 使用 after logon trigger

    NLS_SORT

定义

NLS_SORT 定义了 order by 语句的整理顺序:

  1. 如果 NLS_SORT 为 BINARY sort,则 order by排序基于 字符的numeric value顺序来进行排序(binary排序要求更少的系统负载)
  2. 如果 NLS_SORT 为 linguistic sortorder by排序基于 字符的linguistic sort定义的排序顺序。(Most (but not all) languages supported by the NLS_LANGUAGE parameter also support a linguistic sort with the same name.)

NLS_SORT 的默认值是由 NLS_LANGUAGE 决定的。

索引

索引是根据binary order key排序的。
当将 NLS_SORT 设置为非 BINARY SORT 时: 优化器会在执行计划中,进行全表扫描和全排序操作。
当将 NLS_SORT 设置为 BINARY SORT时: 优化器可以使用索引来进行 order by 排序。

若想建立 按拼音排序的索引: 可以建立 linguistic index

CREATE INDEX nls_index ON my_table (NLSSORT(name, ‘NLS_SORT = SCHINESE_PINYIN_M’));

资料

http://wuaner.iteye.com/blog/681614
https://blog.csdn.net/qincidong/article/details/8998284
https://docs.oracle.com/cd/B19306_01/server.102/b14225/ch3globenv.htm#NLSPG003
https://docs.oracle.com/cd/B19306_01/server.102/b14225/applocaledata.htm
https://www.oracle.com/technetwork/testcontent/sort-083215.html