Spring 项目中把大量的 SQL 分散在 Java 代码中,无 Here Doc 的情况下用加号来连接写着实在是不爽,于是之前思考这个 Spring 项目中把 SQL 语句写在 .sql 文件中 -- 把它们写在 *.sql 文件中,但是这个 *.sql 需要特定的格式来标识属性 Key--!select.user
而且还需要一个额外的类 SqlPropertySourceFactory 来解析上面的 *.sql 文件, 识别出 select.user 是 Key, 紧接着后面的块是相应的属性值,用注解引用它时还有点额外的 factory 属性来配置,如
select id, firstname, lastname, address --!update.user
update ........@PropertySource(value = "classpath:sql/queries.sql", factory = SqlPropertySourceFactory.class)
所以一直在思考是否能够再简单些,是否能用一个自定义的注解,如@SqlPropertySource("classpath:sql/queries.sql")
捉摸了很久,似乎有点难度,不过再不断发掘的过程中找到了这个类org.springframework.core.io.support.PropertiesLoaderUtils, 有下面的代码片断 Read More
Spring 的 JdbcTemplate 为我们操作数据库提供非常大的便利,不需要显式的管理资源和处理异常。在我们进入到了 Java 8 后,JdbcTemplate 方法中的回调函数可以用 Lambda 表达式进行简化,而本文要说的正是这种 Lambda 简化容易给我们带来的一个 Bug, 这是我在一个实际项目中写的单元测试发现的。
下面就是我们的一个样板代码,在我们的UserRespository中有一个方法 findAll() 用于获得所有用户:1public List<User> findAll() { 2 List<User> users = new ArrayList<>(); 3 jdbcTemplate.query("select id, name from user", rs -> { 4 while (rs.next()) { 5 users.add(new User(rs.getInt("id"), rs.getString("name"))); 6 } 7 }); 8 return users; 9}
Read More- 在 Java 中对于泛型类型,比如这样简单的类定义
class Processor<T> {}
如果直接初始化时要指定具体类型的话,我们可以这么写Processor<String> processor = new Processor<>(); //Java 7 及以上版本
Spring 对基本泛型的初始化
如果我们要用 Spring 容器来初始化这个类,比如给上面那个类加个 @Named 注解@Named
这时候我们通过
class Processor<T> {
}beanFactory.getBean(Processor.class)得到的是一个什么样的实例呢?Spring 怎么知道要指定什么具体类型呢?很简单,任何不确定的情况都是 Object。所以通过容器得到的Processor实例相当于用下面代码构造出来的Processor processor = new Processor(); //更准确来讲是 Processor<Object> processor = new Processor<>();
再进一步,对于有上限约束的泛型定义,Spring 才如何应对呢?像 Read More
我们在使用 JDBC 时, 如果把所有的 SQL 语句全写在 Java 文件中, 由于 Java 不支持 Here Document, 多行字符串要么用加号, 要么用 Java 8 的String.join()方法来连接, 同时不能对 SQL 语句进行语法加亮, 所以这样的 SQL 字符串阅读性很差. 别说为何不用 Hibernate 之类的而不直接写原始的 SQL 语句, 在操作复杂的系统时还是会用到 JdbcTemplate 吧.
所以我们希望能把 SQL 语句写在单独的*.sql文件里, 这样很多编辑器就能语法高亮显示, 或在输入时还能得到智能提示. 有种办法是把*.sql用作为属性文件, 那么在其中定义多行的 SQL 语句时就得这样select.user=select id, firstname, lastname, address \
加载后就能用
from users \
where id=?getProperty("select.user")来引用相应的语句了. 属性文件的换行与 Bash 一样, 也是用\, 但如此, 则*.sql并非一个纯粹的 SQL 文件, 不能正确的进行语法加亮, 一旦写上 SQL 的注释--就更是在添乱了.
所以我们的第二个方案是: 首先*.sql就该是一个真正的 SQL 文件, 而不是伪装的属性文件, 为了能在程序中引用每一条 SQL 语句, 我们该如何表示各自的 Key 呢? 这里的灵感仍然是来自于 Linux Shell, 在 Linux Shell 中指定执行环境的用了特殊的注释方式#!, 如#!/bin/bash
Read More
#!/usr/bin/env python
当我们启动一个 Spring Boot 的 Hello World 程序, 可以看到 Spring 会在控制台下输出一段 ASCII 字符组成的 Spring 字样, 像这个图中的样子,
并且 ":: Spring Boot ::" 是绿色显示, 版本号灰色. 如果每个 Spring Boot 做的应用都用默认的 Banner 就不好玩了, 无外乎只在声明我正在用 Spring Boot. 好在 Spring 提供了多种方式让我们定制自己的 Banner.
官方文档: http://docs.spring.io/spring-boot/docs/1.3.8.RELEASE/reference/htmlsingle/#boot-features-banner
初始 Banner 的代码是 SpringApplicationBannerPrinter 类.
Spring Boot 默认寻找 Banner 的顺序是:- 依次在 Classpath 下找 文件
banner.gif,banner.jpg, 和banner.png, 先找到谁就用谁 - 继续 Classpath 下找
banner.txt - 上面都没有找到的话, 用默认的 SpringBootBanner, 就是我们最常见到的那个
- 依次在 Classpath 下找 文件
前阵想试下 Spring MVC 4 有了些什么新特性, 可真正用 Maven 在 IDE 中建立一个项目并不那么容易. Spring 当初在笑 EJB 的笨重时如今把自己也搞大了, 继而出台了一个 Spring Boot 来响应微服务的号召.
Spring Boot 的出世可以大大提升使用 Spring 框架时的开发效率. Spring 尽量简化 Spring 项目的配置, 一个mvn package就轻轻松的把一个 Web 项目打成一个fat jar, 运行java -jar spring-boot-sample-1.0-SNAPSHOT.jar就能通过内嵌的 Tomcat 或 Jetty 来启动一个 Web 应用了, 更别提怎么应对普通控制台应用了.
现在就来体验一下 Spring Boot 做一个 Spring MVC 项目有多简单, 我们仍然是建立一个 Maven 项目, 最简单的pom.xml文件内容如下: Read More- 还是在很久以前,作过一篇 用 AOP 来记录每个方法的执行时间(Spring 或直接 AspectJ), 其中例示了三种方法来拦截方法,用以监测方法调用时间它们分别是:
1. Spring 2.0 用 AspectJ 实现 AOP
2. Spring 通用的方法拦截
3. 直接用 AspectJ 实现
在这里再次使用 <aop:aspect-autoproxy/> 再 @Aspect 注解的方式来写个新的例子。原理与前面基本一致,只是在类里用 @Aspect, @Pointcut, @Before, @After, @Around, @AfterReturning, @AfterThrowing 来写拦截类。
局限仍然是必须通过 Spring 的 BeanFactory 获得的实例才能被拦截到,除非是在 Eclipse 里安装 AJDT 或是使用 Maven-AspectJ Plugin 来编译工程。
好,我们来看完整的例子,下面列出所有的项目文件,这是一个 Maven 的项目,所以从 pom.xml 开始。 Read More - 如何你的DispatcherServlet拦截 .do这样的URL,就不存在访问不到静态资源的问题。如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对.js,*.jpg的访问也就被拦截了。
目的:可以正常访问静态文件,不要找不到静态文件报404。
方案一:激活Tomcat的defaultServlet来处理静态文件1<servlet-mapping> 2 <servlet-name>default</servlet-name> 3 <url-pattern>*.jpg</url-pattern> 4</servlet-mapping> 5<servlet-mapping> 6 <servlet-name>default</servlet-name> 7 <url-pattern>*.js</url-pattern> 8</servlet-mapping> 9<servlet-mapping> 10 <servlet-name>default</servlet-name> 11 <url-pattern>*.css</url-pattern> 12</servlet-mapping>要配置多个,每种文件配置一个 Read MoreSpring MVC 应用在 Tomcat 启动的时候出现了下面的错误:
java.lang.NoSuchFieldError: APPLICATION_CONTEXT_ID_PREFIX
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:430)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:458)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:339)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:306)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)
at javax.servlet.GenericServlet.init(GenericServlet.java:212)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1173)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:993)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4350)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4659)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045) Read More本文通过一个简单的例子,说明如何去扩展XML配置,它大致需要的几个步骤。具体的需求是使用自定义标签定义一个简单的bean,这个bean有一个或多个属性,标签定义完成后,可以在其他项目中用自定义标签来定义该bean。
Spring 2.0版本支持扩展XML配置,着实兴奋了一下,在我看来,Spring作为目前最流行的框架,不能扩展用户自定义的配置,实在是Spring的一个很不爽的地方,的方式用起来比较通用,起码到目前为止符合大部分人的使用习惯,并且能完成Spring所有的配置操作,但是对于第三方的提供商或则会经常扩展Spring功能的开发者来说,使用这样的配置方式或许不是他们最想要的,他们需要使组件的配置更加直观、易阅读、易扩展……试想使用下面的配置方式。 Read More