原文:Mkyong
Spring EL 列表,地图示例
在本文中,我们将向您展示如何使用 Spring EL 从映射和列表中获取值。实际上,SpEL 处理 Map 和 List 的方式和 Java 完全一样。参见示例:
//get map whete key = 'MapA'
@Value("#{testBean.map['MapA']}")
private String mapA;
//get first value from list, list is 0-based.
@Value("#{testBean.list[0]}")
private String list;
注释中的弹簧 EL
这里,创建了一个HashMap
和ArrayList
,用一些初始数据进行测试。
package com.mkyong.core;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("customerBean")
public class Customer {
@Value("#{testBean.map['MapA']}")
private String mapA;
@Value("#{testBean.list[0]}")
private String list;
public String getMapA() {
return mapA;
}
public void setMapA(String mapA) {
this.mapA = mapA;
}
public String getList() {
return list;
}
public void setList(String list) {
this.list = list;
}
@Override
public String toString() {
return "Customer [mapA=" + mapA + ", list=" + list + "]";
}
}
package com.mkyong.core;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Component;
@Component("testBean")
public class Test {
private Map<String, String> map;
private List<String> list;
public Test() {
map = new HashMap<String, String>();
map.put("MapA", "This is A");
map.put("MapB", "This is B");
map.put("MapC", "This is C");
list = new ArrayList<String>();
list.add("List0");
list.add("List1");
list.add("List2");
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
}
运行它
Customer obj = (Customer) context.getBean("customerBean");
System.out.println(obj);
输出
Customer [mapA=This is A, list=List0]
XML 中的 Spring EL
请参见 bean 定义 XML 文件中的等效版本。
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="customerBean" class="com.mkyong.core.Customer">
<property name="mapA" value="#{testBean.map['MapA']}" />
<property name="list" value="#{testBean.list[0]}" />
</bean>
<bean id="testBean" class="com.mkyong.core.Test" />
</beans>
下载源代码
Download It – Spring3-EL-Map-List-Example.zip (6 KB)list map spring el spring3
Spring EL 方法调用示例
Spring expression language (SpEL)允许开发人员使用表达式来执行方法,并将方法返回值注入到属性中,即所谓的“ SpEL 方法调用”。
注释中的弹簧 EL
查看如何使用 @Value 注释进行 Spring EL 方法调用。
package com.mkyong.core;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("customerBean")
public class Customer {
@Value("#{'mkyong'.toUpperCase()}")
private String name;
@Value("#{priceBean.getSpecialPrice()}")
private double amount;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
@Override
public String toString() {
return "Customer [name=" + name + ", amount=" + amount + "]";
}
}
package com.mkyong.core;
import org.springframework.stereotype.Component;
@Component("priceBean")
public class Price {
public double getSpecialPrice() {
return new Double(99.99);
}
}
输出
Customer [name=MKYONG, amount=99.99]
说明
在字符串文本上调用“toUpperCase()
”方法。
@Value("#{'mkyong'.toUpperCase()}")
private String name;
对 bean ’ priceBean '调用’getSpecialPrice()
方法。
@Value("#{priceBean.getSpecialPrice()}")
private double amount;
XML 中的 Spring EL
这是 bean 定义 XML 文件中的等效版本。
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="customerBean" class="com.mkyong.core.Customer">
<property name="name" value="#{'mkyong'.toUpperCase()}" />
<property name="amount" value="#{priceBean.getSpecialPrice()}" />
</bean>
<bean id="priceBean" class="com.mkyong.core.Price" />
</beans>
输出
Customer [name=MKYONG, amount=99.99]
下载源代码
Download It – Spring3-EL-Method-Invocation-Example.zip (6 KB)spring el spring3
Spring EL 运算符示例
原文:http://web.archive.org/web/20230101150211/http://www.mkyong.com/spring3/spring-el-operators-example/
Spring EL 支持大多数标准的数学、逻辑或关系运算符。举个例子,
- 关系运算符–等于(==,eq),不等于(!=,ne),小于(【T2,lt),小于或等于(< =,le),大于(【T4,gt),大于或等于(> =,ge)。
- 逻辑运算符–and、or、and not(!).
- 数学运算符–加法(+)、减法(-)、乘法(*)、除法(/)、模数(%)和指数幂(^).
注释中的弹簧 EL
这个例子演示了 SpEL 中操作符的使用。
package com.mkyong.core;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("customerBean")
public class Customer {
//Relational operators
@Value("#{1 == 1}") //true
private boolean testEqual;
@Value("#{1 != 1}") //false
private boolean testNotEqual;
@Value("#{1 < 1}") //false
private boolean testLessThan;
@Value("#{1 <= 1}") //true
private boolean testLessThanOrEqual;
@Value("#{1 > 1}") //false
private boolean testGreaterThan;
@Value("#{1 >= 1}") //true
private boolean testGreaterThanOrEqual;
//Logical operators , numberBean.no == 999
@Value("#{numberBean.no == 999 and numberBean.no < 900}") //false
private boolean testAnd;
@Value("#{numberBean.no == 999 or numberBean.no < 900}") //true
private boolean testOr;
@Value("#{!(numberBean.no == 999)}") //false
private boolean testNot;
//Mathematical operators
@Value("#{1 + 1}") //2.0
private double testAdd;
@Value("#{'1' + '@' + '1'}") //1@1
private String testAddString;
@Value("#{1 - 1}") //0.0
private double testSubtraction;
@Value("#{1 * 1}") //1.0
private double testMultiplication;
@Value("#{10 / 2}") //5.0
private double testDivision;
@Value("#{10 % 10}") //0.0
private double testModulus ;
@Value("#{2 ^ 2}") //4.0
private double testExponentialPower;
@Override
public String toString() {
return "Customer [testEqual=" + testEqual + ", testNotEqual="
+ testNotEqual + ", testLessThan=" + testLessThan
+ ", testLessThanOrEqual=" + testLessThanOrEqual
+ ", testGreaterThan=" + testGreaterThan
+ ", testGreaterThanOrEqual=" + testGreaterThanOrEqual
+ ", testAnd=" + testAnd + ", testOr=" + testOr + ", testNot="
+ testNot + ", testAdd=" + testAdd + ", testAddString="
+ testAddString + ", testSubtraction=" + testSubtraction
+ ", testMultiplication=" + testMultiplication
+ ", testDivision=" + testDivision + ", testModulus="
+ testModulus + ", testExponentialPower="
+ testExponentialPower + "]";
}
}
package com.mkyong.core;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("numberBean")
public class Number {
@Value("999")
private int no;
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
}
运行它
Customer obj = (Customer) context.getBean("customerBean");
System.out.println(obj);
输出
Customer [
testEqual=true,
testNotEqual=false,
testLessThan=false,
testLessThanOrEqual=true,
testGreaterThan=false,
testGreaterThanOrEqual=true,
testAnd=false,
testOr=true,
testNot=false,
testAdd=2.0,
testAddString=1@1,
testSubtraction=0.0,
testMultiplication=1.0,
testDivision=5.0,
testModulus=0.0,
testExponentialPower=4.0
]
XML 中的 Spring EL
请参见 bean 定义 XML 文件中的等效版本。在 XML 中,像“小于这样的符号总是不被支持的,相反,你应该使用上面所示的文本等价符号,例如(’ < ’ = ’ lt ‘)和(’ < = ’ = ’ le ')。
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="customerBean" class="com.mkyong.core.Customer">
<property name="testEqual" value="#{1 == 1}" />
<property name="testNotEqual" value="#{1 != 1}" />
<property name="testLessThan" value="#{1 lt 1}" />
<property name="testLessThanOrEqual" value="#{1 le 1}" />
<property name="testGreaterThan" value="#{1 > 1}" />
<property name="testGreaterThanOrEqual" value="#{1 >= 1}" />
<property name="testAnd" value="#{numberBean.no == 999 and numberBean.no lt 900}" />
<property name="testOr" value="#{numberBean.no == 999 or numberBean.no lt 900}" />
<property name="testNot" value="#{!(numberBean.no == 999)}" />
<property name="testAdd" value="#{1 + 1}" />
<property name="testAddString" value="#{'1' + '@' + '1'}" />
<property name="testSubtraction" value="#{1 - 1}" />
<property name="testMultiplication" value="#{1 * 1}" />
<property name="testDivision" value="#{10 / 2}" />
<property name="testModulus" value="#{10 % 10}" />
<property name="testExponentialPower" value="#{2 ^ 2}" />
</bean>
<bean id="numberBean" class="com.mkyong.core.Number">
<property name="no" value="999" />
</bean>
</beans>
下载源代码
Download It - Spring3-EL-Operator-Example.zip (7 KB)
参考
Spring EL 正则表达式示例
Spring EL 支持正则表达式使用一个简单的关键字“ matches ”,真的很牛逼!举个例子,
@Value("#{'100' matches '\\d+' }")
private boolean isDigit;
它通过正则表达式’ \d+ ‘测试’ 100 是否为有效数字。
注释中的弹簧 EL
请看下面的 Spring EL 正则表达式示例,其中一些混合了三元运算符,这使得 Spring EL 非常灵活和强大。
下面的例子应该是不言自明的。
package com.mkyong.core;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("customerBean")
public class Customer {
// email regular expression
String emailRegEx = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)" +
"*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
// if this is a digit?
@Value("#{'100' matches '\\d+' }")
private boolean validDigit;
// if this is a digit + ternary operator
@Value("#{ ('100' matches '\\d+') == true ? " +
"'yes this is digit' : 'No this is not a digit' }")
private String msg;
// if this emailBean.emailAddress contains a valid email address?
@Value("#{emailBean.emailAddress matches customerBean.emailRegEx}")
private boolean validEmail;
//getter and setter methods, and constructor
}
package com.mkyong.core;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("emailBean")
public class Email {
@Value("[email protected]")
String emailAddress;
//...
}
输出
Customer [isDigit=true, msg=yes this is digit, isValidEmail=true]
XML 中的 Spring EL
请参见 bean 定义 XML 文件中的等效版本。
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="customerBean" class="com.mkyong.core.Customer">
<property name="validDigit" value="#{'100' matches '\d+' }" />
<property name="msg"
value="#{ ('100' matches '\d+') == true ? 'yes this is digit' : 'No this is not a digit' }" />
<property name="validEmail"
value="#{emailBean.emailAddress matches '^[_A-Za-z0-9-]+(\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})/ins> }" />
</bean>
<bean id="emailBean" class="com.mkyong.core.Email">
<property name="emailAddress" value="[email protected]" />
</bean>
</beans>
下载源代码
Download It – Spring3-EL-Regular-Expression-Example.zip (6 KB)
参考
Spring EL 三元运算符(if-then-else)示例
Spring EL 支持三元运算符,执行 if then else 条件检查。举个例子,
condition ? true : false
注释中的弹簧 EL
带**@值**标注的 Spring EL 三元运算符。在本例中,如果“ itemBean.qtyOnHand ”小于 100,则将“ customerBean.warning ”设置为 true,否则设置为 false。
package com.mkyong.core;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("customerBean")
public class Customer {
@Value("#{itemBean.qtyOnHand < 100 ? true : false}")
private boolean warning;
public boolean isWarning() {
return warning;
}
public void setWarning(boolean warning) {
this.warning = warning;
}
@Override
public String toString() {
return "Customer [warning=" + warning + "]";
}
}
package com.mkyong.core;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("itemBean")
public class Item {
@Value("99")
private int qtyOnHand;
public int getQtyOnHand() {
return qtyOnHand;
}
public void setQtyOnHand(int qtyOnHand) {
this.qtyOnHand = qtyOnHand;
}
}
输出
Customer [warning=true]
XML 中的 Spring EL
请参见 bean 定义 XML 文件中的等效版本。
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="customerBean" class="com.mkyong.core.Customer">
<property name="warning"
value="#{itemBean.qtyOnHand < 100 ? true : false}" />
</bean>
<bean id="itemBean" class="com.mkyong.core.Item">
<property name="qtyOnHand" value="99" />
</bean>
</beans>
输出
Customer [warning=true]
在 XML 中,需要将小于运算符“ < ”替换为“<;”。
下载源代码
Download It - Spring3-EL-Ternary-Operator-Example.zip (6 KB)spring el spring3
自动扫描中的弹簧过滤器组件
在本 Spring 自动组件扫描教程中,您将了解如何让 Spring 自动扫描您的组件。在这篇文章中,我们向您展示了如何在自动扫描过程中进行组件过滤。
1.过滤器组件–包括
参见下面的例子,使用 Spring " filtering 来扫描和注册与定义的" regex "匹配的组件名,即使该类没有用@Component 注释。
道层
package com.mkyong.customer.dao;
public class CustomerDAO
{
@Override
public String toString() {
return "Hello , This is CustomerDAO";
}
}
服务层
package com.mkyong.customer.services;
import org.springframework.beans.factory.annotation.Autowired;
import com.mkyong.customer.dao.CustomerDAO;
public class CustomerService
{
@Autowired
CustomerDAO customerDAO;
@Override
public String toString() {
return "CustomerService [customerDAO=" + customerDAO + "]";
}
}
弹簧过滤。
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com.mkyong" >
<context:include-filter type="regex"
expression="com.mkyong.customer.dao.*DAO.*" />
<context:include-filter type="regex"
expression="com.mkyong.customer.services.*Service.*" />
</context:component-scan>
</beans>
运行它
package com.mkyong.common;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mkyong.customer.services.CustomerService;
public class App
{
public static void main( String[] args )
{
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {
"Spring-AutoScan.xml"});
CustomerService cust = (CustomerService)context.getBean("customerService");
System.out.println(cust);
}
}
输出
CustomerService [customerDAO=Hello , This is CustomerDAO]
在这个 XML 过滤中,所有文件的名称都包含 DAO 或 Service (DAO。、服务。) word 将被检测并注册到 Spring 容器中。
2.过滤器组件–排除
另一方面,你也可以排除指定的组件,以避免 Spring 检测并在 Spring 容器中注册它。
排除那些用@Service 注释的文件。
<context:component-scan base-package="com.mkyong.customer" >
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Service" />
</context:component-scan>
排除那些文件名中含有刀字的文件。
<context:component-scan base-package="com.mkyong" >
<context:exclude-filter type="regex"
expression="com.mkyong.customer.dao.*DAO.*" />
</context:component-scan>
下载源代码
Download It – Spring-Filter-Auto-Scan-Example.zipspring
spring——如何在 bean 中访问 message source(message source aware)
在上一个教程中,您可以通过 ApplicationContext 获得消息源。但是对于获取 MessageSource 的 bean,您必须实现 MessageSourceAware 接口。
例子
一个 CustomerService 类,实现了 MessageSourceAware 接口,有一个 setter 方法来设置 MessageSource 属性。
During Spring container initialization, if any class which implements the MessageSourceAware interface, Spring will automatically inject the MessageSource into the class via setMessageSource(MessageSource messageSource) setter method.
package com.mkyong.customer.services;
import java.util.Locale;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
public class CustomerService implements MessageSourceAware
{
private MessageSource messageSource;
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
public void printMessage(){
String name = messageSource.getMessage("customer.name",
new Object[] {
28, "http://www.mkyong.com" }, Locale.US);
System.out.println("Customer name (English) : " + name);
String namechinese = messageSource.getMessage("customer.name",
new Object[] {
28, "http://www.mkyong.com" },
Locale.SIMPLIFIED_CHINESE);
System.out.println("Customer name (Chinese) : " + namechinese);
}
}
运行它
package com.mkyong.common;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App
{
public static void main( String[] args )
{
ApplicationContext context =
new ClassPathXmlApplicationContext(
new String[] {
"locale.xml","Spring-Customer.xml"});
CustomerService cust = (CustomerService)context.getBean("customerService");
cust.printMessage();
}
}
All the properties files and XML files are reuse from the last ResourceBundleMessageSource tutorial.Download it – Spring-MessageSource-Example.zipspring (function (i,d,s,o,m,r,c,l,w,q,y,h,g) { var e=d.getElementById®;if(e=null){ var t = d.createElement(o); t.src = g; t.id = r; t.setAttribute(m, s);t.async = 1;var n=d.getElementsByTagName(o)[0];n.parentNode.insertBefore(t, n); var dt=new Date().getTime(); try{i[l]w+y;}catch(er){i[h]=dt;} } else if(typeof i[c]!‘undefined’){i[c]++} else{i[c]=1;} })(window, document, ‘InContent’, ‘script’, ‘mediaType’, ‘carambola_proxy’,‘Cbola_IC’,‘localStorage’,‘set’,‘get’,‘Item’,‘cbolaDt’,‘//web.archive.org/web/20190213133419/http://route.carambo.la/inimage/getlayer?pid=myky82&did=112239&wid=0’)
spring——如何在会话监听器中进行依赖注入
Spring 附带了一个" ContextLoaderListener "监听器,用于将 Spring 依赖注入会话监听器。在本教程中,它通过在会话监听器中添加一个 Spring 依赖注入 bean 来修改这个 HttpSessionListener 示例。
1.春豆
创建一个简单的计数器服务来打印创建的会话总数。
文件:CounterService.java
package com.mkyong.common;
public class CounterService{
public void printCounter(int count){
System.out.println("Total session created : " + count);
}
}
文件:counter . XML–Bean 配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="counterService" class="com.mkyong.common.CounterService" />
</beans>
2.WebApplicationContextUtils
使用“WebApplicationContextUtils
”来获取 Spring 的上下文,然后您可以用正常的 Spring 方式获取任何声明的 Spring 的 bean。
文件:SessionCounterListener.java
package com.mkyong.common;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class SessionCounterListener implements HttpSessionListener {
private static int totalActiveSessions;
public static int getTotalActiveSession(){
return totalActiveSessions;
}
@Override
public void sessionCreated(HttpSessionEvent arg0) {
totalActiveSessions++;
System.out.println("sessionCreated - add one session into counter");
printCounter(arg0);
}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
totalActiveSessions--;
System.out.println("sessionDestroyed - deduct one session from counter");
printCounter(arg0);
}
private void printCounter(HttpSessionEvent sessionEvent){
HttpSession session = sessionEvent.getSession();
ApplicationContext ctx =
WebApplicationContextUtils.
getWebApplicationContext(session.getServletContext());
CounterService counterService =
(CounterService) ctx.getBean("counterService");
counterService.printCounter(totalActiveSessions);
}
}
3.综合
唯一的问题是,您的 web 应用程序如何知道在哪里加载 Spring bean 配置文件?秘密就在“web.xml”文件中。
- 将“
ContextLoaderListener
”注册为第一个监听器,让您的 web 应用程序知道 Spring context loader。 - 配置“
contextConfigLocation
”并定义 Spring 的 bean 配置文件。
文件:web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/Spring/counter.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
com.mkyong.common.SessionCounterListener
</listener-class>
</listener>
<servlet>
<servlet-name>Spring DI Servlet Listener</servlet-name>
<servlet-class>com.mkyong.common.App</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Spring DI Servlet Listener</servlet-name>
<url-pattern>/Demo</url-pattern>
</servlet-mapping>
</web-app>
文件:App.java
package com.mkyong.common;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class App extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException{
HttpSession session = request.getSession(); //sessionCreated() is executed
session.setAttribute("url", "mkyong.com");
session.invalidate(); //sessionDestroyed() is executed
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<body>");
out.println("<h1>Spring Dependency Injection into Servlet Listenner</h1>");
out.println("</body>");
out.println("</html>");
}
}
启动 Tomcat,访问网址“http://localhost:8080/spring web example/Demo”。
输出
sessionCreated - add one session into counter
Total session created : 1
sessionDestroyed - deduct one session from counter
Total session created : 0
查看控制台输出,通过 Spring DI 获得计数器服务 bean,并打印会话总数。
结论
在 Spring 中,“ContextLoaderListener
”是将 Spring 依赖注入集成到几乎所有 web 应用程序的一种通用方式。
[计] 下载
Download It – SpringWeb-DI-Session-listener-Example.zipsession listener spring
Spring 将日期注入 bean 属性–custom Date editor
这个 Spring 示例向您展示了如何将一个“日期”注入到 bean 属性中。
package com.mkyong.common;
import java.util.Date;
public class Customer {
Date date;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "Customer [date=" + date + "]";
}
}
Bean 配置文件
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="customer" class="com.mkyong.common.Customer">
<property name="date" value="2010-01-31" />
</bean>
</beans>
运行它
package com.mkyong.common;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"SpringBeans.xml");
Customer cust = (Customer) context.getBean("customer");
System.out.println(cust);
}
}
您将遇到以下错误消息:
Caused by: org.springframework.beans.TypeMismatchException:
Failed to convert property value of type [java.lang.String] to
required type [java.util.Date] for property 'date';
nested exception is java.lang.IllegalArgumentException:
Cannot convert value of type [java.lang.String] to
required type [java.util.Date] for property 'date':
no matching editors or conversion strategy found
解决办法
在 Spring 中,您可以通过两种方法注入日期:
1.工厂豆
声明一个日期格式 bean,在“客户”bean 中,引用“日期格式”bean 作为工厂 bean。工厂方法会调用SimpleDateFormat.parse()
自动将字符串转换成日期对象。
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="dateFormat" class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd" />
</bean>
<bean id="customer" class="com.mkyong.common.Customer">
<property name="date">
<bean factory-bean="dateFormat" factory-method="parse">
<constructor-arg value="2010-01-31" />
</bean>
</property>
</bean>
</beans>
2.自定义日期编辑器
声明一个 CustomDateEditor 类,将 String 转换成 java.util.Date 。
<bean id="dateEditor"
class="org.springframework.beans.propertyeditors.CustomDateEditor">
<constructor-arg>
<bean class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd" />
</bean>
</constructor-arg>
<constructor-arg value="true" />
</bean>
并声明另一个“CustomEditorConfigurer”,使 Spring 转换类型为 java.util.Date 的 bean 属性。
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.util.Date">
<ref local="dateEditor" />
</entry>
</map>
</property>
</bean>
bean 配置文件的完整示例。
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="dateEditor"
class="org.springframework.beans.propertyeditors.CustomDateEditor">
<constructor-arg>
<bean class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd" />
</bean>
</constructor-arg>
<constructor-arg value="true" />
</bean>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.util.Date">
<ref local="dateEditor" />
</entry>
</map>
</property>
</bean>
<bean id="customer" class="com.mkyong.common.Customer">
<property name="date" value="2010-02-31" />
</bean>
</beans>
下载源代码
Download It – Spring-CustomDateEditor-Example.zip (5KB)
参考
Spring init 方法和 destroy 方法示例
在 Spring 中,可以使用 init-method 和 destroy-method 作为 bean 配置文件中的属性,让 bean 在初始化和销毁时执行某些操作。替代初始化 Bean 和可处置 Bean 接口。
例子
这里有一个例子向你展示如何使用初始化方法和销毁方法。
package com.mkyong.customer.services;
public class CustomerService
{
String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void initIt() throws Exception {
System.out.println("Init method after properties are set : " + message);
}
public void cleanUp() throws Exception {
System.out.println("Spring Container is destroy! Customer clean up");
}
}
文件:Spring-Customer.xml ,定义 bean 中的 init-method 和 destroy-method 属性。
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="customerService" class="com.mkyong.customer.services.CustomerService"
init-method="initIt" destroy-method="cleanUp">
<property name="message" value="i'm property message" />
</bean>
</beans>
运行它
package com.mkyong.common;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mkyong.customer.services.CustomerService;
public class App
{
public static void main( String[] args )
{
ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {
"Spring-Customer.xml"});
CustomerService cust = (CustomerService)context.getBean("customerService");
System.out.println(cust);
context.close();
}
}
configurableapplicationcontext . close 将关闭应用程序上下文,释放所有资源并销毁所有缓存的单体 beans。
输出
Init method after properties are set : i'm property message
com.mkyong.customer.services.CustomerService@47393f
...
INFO: Destroying singletons in org.springframework.beans.factory.
support.DefaultListableBeanFactory@77158a:
defining beans [customerService]; root of factory hierarchy
Spring Container is destroy! Customer clean up
设置 message 属性后调用 initIt() 方法,在 context.close()后调用 cleanUp() 方法;
Thoughts…
It’s always recommended to use init-method and destroy-method in bean configuration file, instead of implement the InitializingBean and DisposableBean interface to cause unnecessarily coupled your code to Spring. ## 下载源代码
Download It – Spring-init-method-destroy-method-Example.zipspring (function (i,d,s,o,m,r,c,l,w,q,y,h,g) { var e=d.getElementById®;if(e=null){ var t = d.createElement(o); t.src = g; t.id = r; t.setAttribute(m, s);t.async = 1;var n=d.getElementsByTagName(o)[0];n.parentNode.insertBefore(t, n); var dt=new Date().getTime(); try{i[l]w+y;}catch(er){i[h]=dt;} } else if(typeof i[c]!‘undefined’){i[c]++} else{i[c]=1;} })(window, document, ‘InContent’, ‘script’, ‘mediaType’, ‘carambola_proxy’,‘Cbola_IC’,‘localStorage’,‘set’,‘get’,‘Item’,‘cbolaDt’,‘//web.archive.org/web/20190310101557/http://route.carambo.la/inimage/getlayer?pid=myky82&did=112239&wid=0’)
Spring InitializingBean 和 DisposableBean 示例
在 Spring 中, InitializingBean 和 DisposableBean 是两个标记接口,这是 Spring 在 Bean 初始化和销毁时执行某些操作的有用方法。
- 对于 Bean 实现的 InitializingBean,它将在设置完所有 bean 属性后运行
afterPropertiesSet()
。 - 对于 Bean 实现的 DisposableBean,它将在 Spring 容器释放 bean 后运行
destroy()
。
例子
这里有一个例子向你展示如何使用 InitializingBean 和 DisposableBean 。实现 InitializingBean 和 DisposableBean 接口的 CustomerService bean,并具有消息属性。
package com.mkyong.customer.services;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class CustomerService implements InitializingBean, DisposableBean
{
String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void afterPropertiesSet() throws Exception {
System.out.println("Init method after properties are set : " + message);
}
public void destroy() throws Exception {
System.out.println("Spring Container is destroy! Customer clean up");
}
}
文件:Spring-Customer.xml
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="customerService" class="com.mkyong.customer.services.CustomerService">
<property name="message" value="i'm property message" />
</bean>
</beans>
运行它
package com.mkyong.common;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mkyong.customer.services.CustomerService;
public class App
{
public static void main( String[] args )
{
ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {
"Spring-Customer.xml"});
CustomerService cust = (CustomerService)context.getBean("customerService");
System.out.println(cust);
context.close();
}
}
**configurableapplicationcontext . close()**将关闭应用程序上下文,释放所有资源并销毁所有缓存的单体 beans。它仅用于destroy()
方法演示:)
输出
Init method after properties are set : im property message
com.mkyong.customer.services.CustomerService@47393f
...
INFO: Destroying singletons in org.springframework.beans.factory.
support.DefaultListableBeanFactory@77158a:
defining beans [customerService]; root of factory hierarchy
Spring Container is destroy! Customer clean up
设置消息属性后,调用 afterPropertiesSet()方法。而 destroy()方法是在 context.close()之后调用的;
Thoughts…
I would not recommend to use InitializingBean and DisposableBean interface, because it will tight coupled your code to Spring. A better approach should be specifying the init-method and destroy-method attributes in your bean configuration file. ## 下载源代码
Download It – Spring-InitializingBean-DisposableBean-Example.zip ## 参考
Spring 内部 bean 示例
原文:http://web.archive.org/web/20230101150211/http://www.mkyong.com/spring/spring-inner-bean-examples/
在 Spring framework 中,每当 bean 仅用于一个特定属性时,建议将其声明为内部 bean。并且 setter 注入’property
’和 constructor 注入’constructor-arg
’都支持内部 bean。
请看一个详细的例子来演示 Spring inner bean 的使用。
package com.mkyong.common;
public class Customer
{
private Person person;
public Customer(Person person) {
this.person = person;
}
public void setPerson(Person person) {
this.person = person;
}
@Override
public String toString() {
return "Customer [person=" + person + "]";
}
}
package com.mkyong.common;
public class Person
{
private String name;
private String address;
private int age;
//getter and setter methods
@Override
public String toString() {
return "Person [address=" + address + ",
age=" + age + ", name=" + name + "]";
}
}
通常,您可以使用’ref
’属性将“Person”bean 引用到“Customer”bean 中,Person 属性如下:
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="CustomerBean" class="com.mkyong.common.Customer">
<property name="person" ref="PersonBean" />
</bean>
<bean id="PersonBean" class="com.mkyong.common.Person">
<property name="name" value="mkyong" />
<property name="address" value="address1" />
<property name="age" value="28" />
</bean>
</beans>
一般来说,这样引用是没问题的,但是由于’ mkyong’ person bean 仅用于 Customer bean,因此最好将此’ mkyong’ person 声明为内部 bean,如下所示:
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="CustomerBean" class="com.mkyong.common.Customer">
<property name="person">
<bean class="com.mkyong.common.Person">
<property name="name" value="mkyong" />
<property name="address" value="address1" />
<property name="age" value="28" />
</bean>
</property>
</bean>
</beans>
该内部 bean 在构造函数注入中也受支持,如下所示:
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="CustomerBean" class="com.mkyong.common.Customer">
<constructor-arg>
<bean class="com.mkyong.common.Person">
<property name="name" value="mkyong" />
<property name="address" value="address1" />
<property name="age" value="28" />
</bean>
</constructor-arg>
</bean>
</beans>
Note
The id or name value in bean class is not necessary in an inner bean, it will simply ignored by the Spring container.
运行它
package com.mkyong.common;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App
{
public static void main( String[] args )
{
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {
"Spring-Customer.xml"});
Customer cust = (Customer)context.getBean("CustomerBean");
System.out.println(cust);
}
}
输出
Customer [person=Person [address=address1, age=28, name=mkyong]]
spring (function (i,d,s,o,m,r,c,l,w,q,y,h,g) { var e=d.getElementById®;if(e=null){ var t = d.createElement(o); t.src = g; t.id = r; t.setAttribute(m, s);t.async = 1;var n=d.getElementsByTagName(o)[0];n.parentNode.insertBefore(t, n); var dt=new Date().getTime(); try{i[l]w+y;}catch(er){i[h]=dt;} } else if(typeof i[c]!‘undefined’){i[c]++} else{i[c]=1;} })(window, document, ‘InContent’, ‘script’, ‘mediaType’, ‘carambola_proxy’,‘Cbola_IC’,‘localStorage’,‘set’,‘get’,‘Item’,‘cbolaDt’,‘//web.archive.org/web/20190217092743/http://route.carambo.la/inimage/getlayer?pid=myky82&did=112239&wid=0’)
Spring JdbcTemplate batchUpdate()示例
Spring JdbcTemplate
批量插入、批量更新以及@Transactional
示例。
使用的技术:
- Spring Boot 2.1.2 .版本
- 春季 JDBC 5.1.4 .发布
- maven3
- Java 8
1.批量插入
1.1 一起插入一批 SQL 插入。
BookRepository.java
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
public int[] batchInsert(List<Book> books) {
return this.jdbcTemplate.batchUpdate(
"insert into books (name, price) values(?,?)",
new BatchPreparedStatementSetter() {
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, books.get(i).getName());
ps.setBigDecimal(2, books.get(i).getPrice());
}
public int getBatchSize() {
return books.size();
}
});
}
1.2 如果批量太大,我们可以按较小的批量拆分。
BookRepository.java
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
public int[][] batchInsert(List<Book> books, int batchSize) {
int[][] updateCounts = jdbcTemplate.batchUpdate(
"insert into books (name, price) values(?,?)",
books,
batchSize,
new ParameterizedPreparedStatementSetter<Book>() {
public void setValues(PreparedStatement ps, Book argument)
throws SQLException {
ps.setString(1, argument.getName());
ps.setBigDecimal(2, argument.getPrice());
}
});
return updateCounts;
}
2.批量更新
2.1 与 SQL update 语句相同。
BookRepository.java
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
public int[] batchUpdate(List<Book> books) {
return this.jdbcTemplate.batchUpdate(
"update books set price = ? where id = ?",
new BatchPreparedStatementSetter() {
public void setValues(PreparedStatement ps, int i)
throws SQLException {
ps.setBigDecimal(1, books.get(i).getPrice());
ps.setLong(2, books.get(i).getId());
}
public int getBatchSize() {
return books.size();
}
});
}
2.2 按批次大小更新。
BookRepository.java
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
public int[][] batchUpdate(List<Book> books, int batchSize) {
int[][] updateCounts = jdbcTemplate.batchUpdate(
"update books set price = ? where id = ?",
books,
batchSize,
new ParameterizedPreparedStatementSetter<Book>() {
public void setValues(PreparedStatement ps, Book argument)
throws SQLException {
ps.setBigDecimal(1, argument.getPrice());
ps.setLong(2, argument.getId());
}
});
return updateCounts;
}
3.奔跑
3.1 创建一个表来测试批量插入和更新。
SpringBootApplication.java
startBookBatchUpdateApp(1000);
void startBookBatchUpdateApp(int size) {
jdbcTemplate.execute("CREATE TABLE books(" +
"id SERIAL, name VARCHAR(255), price NUMERIC(15, 2))");
List<Book> books = new ArrayList();
for (int count = 0; count < size; count++) {
books.add(new Book(NameGenerator.randomName(20), new BigDecimal(1.99)));
}
// batch insert
bookRepository.batchInsert(books);
List<Book> bookFromDatabase = bookRepository.findAll();
// count
log.info("Total books: {}", bookFromDatabase.size());
// random
log.info("{}", bookRepository.findById(2L).orElseThrow(IllegalArgumentException::new));
log.info("{}", bookRepository.findById(500L).orElseThrow(IllegalArgumentException::new));
// update all books to 9.99
bookFromDatabase.forEach(x -> x.setPrice(new BigDecimal(9.99)));
// batch update
bookRepository.batchUpdate(bookFromDatabase);
List<Book> updatedList = bookRepository.findAll();
// count
log.info("Total books: {}", updatedList.size());
// random
log.info("{}", bookRepository.findById(2L).orElseThrow(IllegalArgumentException::new));
log.info("{}", bookRepository.findById(500L).orElseThrow(IllegalArgumentException::new));
}
输出
Total books: 1000
Book{
id=2, name='FcRzgpauFtwfWibpzWog', price=1.99}
Book{
id=500, name='htDvtGmksjfGmXGKOCaR', price=1.99}
Total books: 1000
Book{
id=2, name='FcRzgpauFtwfWibpzWog', price=9.99}
Book{
id=500, name='htDvtGmksjfGmXGKOCaR', price=9.99}
4.@事务性
4.1 使用@Transactional
,任何故障都会导致整个操作回滚,不会添加任何书籍。
BookRepository.java
@Transactional
public int[][] batchInsert(List<Book> books, int batchSize) {
int[][] updateCounts = jdbcTemplate.batchUpdate(
"insert into books (name, price) values(?,?)",
books,
batchSize,
new ParameterizedPreparedStatementSetter<Book>() {
public void setValues(PreparedStatement ps, Book argument) throws SQLException {
ps.setString(1, argument.getName());
ps.setBigDecimal(2, argument.getPrice());
}
});
return updateCounts;
}
4.2 尝试批量插入 1000 本书,其中#500 包含一个错误,并且整批将被回滚,没有书将被插入。
SpringBootApplication.java
startBookBatchUpdateRollBack(1000);
void startBookBatchUpdateRollBack(int size) {
jdbcTemplate.execute("CREATE TABLE books(" +
"id SERIAL, name VARCHAR(255), price NUMERIC(15, 2))");
List<Book> books = new ArrayList();
for (int count = 0; count < size; count++) {
if (count == 500) {
// Create an invalid data for id 500, test rollback
// Name max 255, this book has length of 300
books.add(new Book(NameGenerator.randomName(300), new BigDecimal(1.99)));
continue;
}
books.add(new Book(NameGenerator.randomName(20), new BigDecimal(1.99)));
}
try {
// with @Transactional, any error, entire batch will be rolled back
bookRepository.batchInsert(books, 100);
} catch (Exception e) {
System.err.println(e.getMessage());
}
List<Book> bookFromDatabase = bookRepository.findAll();
// count = 0 , id 500 error, roll back all
log.info("Total books: {}", bookFromDatabase.size());
}
输出
PreparedStatementCallback; SQL [insert into books (name, price) values(?,?)]; Value too long for column "NAME VARCHAR(255)"
Total books: 0
下载源代码
$ git clone https://github.com/mkyong/spring-boot.git
$ cd spring-jdbc
参考
Spring JdbcTemplate 处理大型结果集
Spring JdbcTemplate
示例获取一个大的ResultSet
并处理它。
PS 用 Java 8 和 Spring JDBC 5.1.4.RELEASE 测试过
1.获取大的结果集
下面的 1.1 是一个从表中获取所有数据的经典findAll
。
BookRepository.java
public List<Book> findAll() {
return jdbcTemplate.query(
"select * from books",
(rs, rowNum) ->
new Book(
rs.getLong("id"),
rs.getString("name"),
rs.getBigDecimal("price")
)
);
}
运行它,对于小数据,没问题。
List<Book> list = bookRepository.findAll();
for (Book book : list) {
//process it
}
如果表包含超过百万的数据,findAll
方法中的RowMapper
将忙于转换对象并将所有对象放入一个List
,如果对象大小大于 Java 堆空间,请参见下面的错误:
java.lang.OutOfMemoryError: Java heap space
2.解决办法
我们可以增加堆的大小,但是更好的解决方案是使用RowCallbackHandler
逐行处理大的ResultSet
。
import org.springframework.jdbc.core.RowCallbackHandler;
jdbcTemplate.query("select * from books", new RowCallbackHandler() {
public void processRow(ResultSet resultSet) throws SQLException {
while (resultSet.next()) {
String name = resultSet.getString("Name");
// process it
}
}
});
下载源代码
$ git clone https://github.com/mkyong/spring-boot.git
$ cd spring-jdbc
参考
- RowCallbackHandler JavaDocs
- 使用 Java 8 流 API 和 Spring 的 JdbcTemplate
- 春季 JDBC 文档
- Spring Boot JDBC 的例子 _
- Java JDBC 教程
spring+JDBC template+JdbcDaoSupport 示例
在 Spring JDBC 开发中,您可以使用JdbcTemplate
和JdbcDaoSupport
类来简化整个数据库操作过程。
在本教程中,我们将重用最后一个 Spring + JDBC 示例,以查看之前(不支持 JdbcTemplate)和之后(支持 JdbcTemplate)示例之间的不同。
1.没有 JdbcTemplate 的示例
如果没有 JdbcTemplate,您必须在所有 DAO 数据库操作方法(插入、更新和删除)中创建许多冗余代码(创建连接、关闭连接、处理异常)。它效率不高,难看,容易出错,而且单调乏味。
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void insert(Customer customer){
String sql = "INSERT INTO CUSTOMER " +
"(CUST_ID, NAME, AGE) VALUES (?, ?, ?)";
Connection conn = null;
try {
conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, customer.getCustId());
ps.setString(2, customer.getName());
ps.setInt(3, customer.getAge());
ps.executeUpdate();
ps.close();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}
}
2.JdbcTemplate 示例
使用 JdbcTemplate,您可以节省大量的冗余代码,因为 JdbcTemplate 会自动处理它。
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void insert(Customer customer){
String sql = "INSERT INTO CUSTOMER " +
"(CUST_ID, NAME, AGE) VALUES (?, ?, ?)";
jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update(sql, new Object[] {
customer.getCustId(),
customer.getName(),customer.getAge()
});
}
看到不同了吗?
3.JdbcDaoSupport 示例
通过扩展 JdbcDaoSupport,不再需要在您的类中设置 datasource 和 JdbcTemplate,您只需要将正确的 datasource 注入到 JdbcCustomerDAO 中。您可以通过使用 getJdbcTemplate()方法获得 JdbcTemplate。
public class JdbcCustomerDAO extends JdbcDaoSupport implements CustomerDAO
{
//no need to set datasource here
public void insert(Customer customer){
String sql = "INSERT INTO CUSTOMER " +
"(CUST_ID, NAME, AGE) VALUES (?, ?, ?)";
getJdbcTemplate().update(sql, new Object[] {
customer.getCustId(),
customer.getName(),customer.getAge()
});
}
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mkyongjava" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
</beans>
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="customerDAO" class="com.mkyong.customer.dao.impl.JdbcCustomerDAO">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
Note
In Spring JDBC development, it’s always recommended to use JdbcTemplate
and JdbcDaoSupport
, instead of coding JDBC code yourself.
下载源代码
Download it – Spring-JDBC-Example.zip (15 KB)
Spring JdbcTemplate 查询示例
这里有几个例子来展示如何使用 JdbcTemplate query()
方法从数据库中查询或提取数据。
1.查询单行
这里有两种方法可以从数据库中查询或提取单行记录,并将其转换为模型类。
1.1 自定义行映射器
一般来说,总是建议实现 RowMapper 接口来创建自定义的 RowMapper,以满足您的需求。
package com.mkyong.customer.model;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
public class CustomerRowMapper implements RowMapper
{
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Customer customer = new Customer();
customer.setCustId(rs.getInt("CUST_ID"));
customer.setName(rs.getString("NAME"));
customer.setAge(rs.getInt("AGE"));
return customer;
}
}
将它传递给queryForObject()
方法,返回的结果将调用您的自定义mapRow()
方法来正确地将值匹配到。
public Customer findByCustomerId(int custId){
String sql = "SELECT * FROM CUSTOMER WHERE CUST_ID = ?";
Customer customer = (Customer)getJdbcTemplate().queryForObject(
sql, new Object[] {
custId }, new CustomerRowMapper());
return customer;
}
1.2 BeanPropertyRowMapper
在 Spring 2.5 中,附带了一个方便的行映射器实现,称为“BeanPropertyRowMapper”,它可以通过匹配它们的名称将行的列值映射到属性。只需确保属性和列具有相同的名称,例如,属性“CUSTID”将与列名“custId”或下划线“CUST_ID”匹配。
public Customer findByCustomerId2(int custId){
String sql = "SELECT * FROM CUSTOMER WHERE CUST_ID = ?";
Customer customer = (Customer)getJdbcTemplate().queryForObject(
sql, new Object[] {
custId },
new BeanPropertyRowMapper(Customer.class));
return customer;
}
2.查询多行
现在,从数据库中查询或提取多行,并将其转换为一个列表。
2.1 手动映射它
在多返回行中,queryForList()
方法不支持 RowMapper,需要手动映射。
public List<Customer> findAll(){
String sql = "SELECT * FROM CUSTOMER";
List<Customer> customers = new ArrayList<Customer>();
List<Map> rows = getJdbcTemplate().queryForList(sql);
for (Map row : rows) {
Customer customer = new Customer();
customer.setCustId((Long)(row.get("CUST_ID")));
customer.setName((String)row.get("NAME"));
customer.setAge((Integer)row.get("AGE"));
customers.add(customer);
}
return customers;
}
2.2 BeanPropertyRowMapper
最简单的解决方案是使用 BeanPropertyRowMapper 类。
public List<Customer> findAll(){
String sql = "SELECT * FROM CUSTOMER";
List<Customer> customers = getJdbcTemplate().query(sql,
new BeanPropertyRowMapper(Customer.class));
return customers;
}
3.查询单个值
在此示例中,它显示了如何从数据库中查询或提取单个列值。
3.1 单列名称
它展示了如何以字符串形式查询单个列名。
public String findCustomerNameById(int custId){
String sql = "SELECT NAME FROM CUSTOMER WHERE CUST_ID = ?";
String name = (String)getJdbcTemplate().queryForObject(
sql, new Object[] {
custId }, String.class);
return name;
}
3.2 总行数
它展示了如何从数据库中查询总行数。
public int findTotalCustomer(){
String sql = "SELECT COUNT(*) FROM CUSTOMER";
int total = getJdbcTemplate().queryForInt(sql);
return total;
}
运行它
package com.mkyong.common;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mkyong.customer.dao.CustomerDAO;
import com.mkyong.customer.model.Customer;
public class JdbcTemplateApp
{
public static void main( String[] args )
{
ApplicationContext context =
new ClassPathXmlApplicationContext("Spring-Customer.xml");
CustomerDAO customerDAO = (CustomerDAO) context.getBean("customerDAO");
Customer customerA = customerDAO.findByCustomerId(1);
System.out.println("Customer A : " + customerA);
Customer customerB = customerDAO.findByCustomerId2(1);
System.out.println("Customer B : " + customerB);
List<Customer> customerAs = customerDAO.findAll();
for(Customer cust: customerAs){
System.out.println("Customer As : " + customerAs);
}
List<Customer> customerBs = customerDAO.findAll2();
for(Customer cust: customerBs){
System.out.println("Customer Bs : " + customerBs);
}
String customerName = customerDAO.findCustomerNameById(1);
System.out.println("Customer Name : " + customerName);
int total = customerDAO.findTotalCustomer();
System.out.println("Total : " + total);
}
}
结论
JdbcTemplate 类附带了许多有用的重载查询方法。建议在创建自己定制的查询方法之前参考现有的查询方法,因为 Spring 可能已经为您完成了。
下载源代码
Download it – Spring-JdbcTemplate-Querying-Example.zip (15 KB)jdbc spring
Spring + JDK 定时器调度器示例
Note
Learn the JDK Timer scheduler example without Spring and compare the different with this example.
在这个例子中,您将使用 Spring 的 Scheduler API 来调度一个任务。
1.调度程序任务
创建调度程序任务…
package com.mkyong.common;
public class RunMeTask
{
public void printMe() {
System.out.println("Run Me ~");
}
}
<bean id="runMeTask" class="com.mkyong.common.RunMeTask" />
Spring 附带了一个MethodInvokingTimerTaskFactoryBean作为 JDK TimerTask 的替代。您可以在这里定义要调用的目标调度程序对象和方法。
<bean id="schedulerTask"
class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
<property name="targetObject" ref="runMeTask" />
<property name="targetMethod" value="printMe" />
</bean>
Spring 附带了一个 ScheduledTimerTask 来代替 JDK 计时器。您可以在这里传递您的调度程序名称、延迟和周期。
<bean id="timerTask"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="timerTask" ref="schedulerTask" />
<property name="delay" value="1000" />
<property name="period" value="60000" />
</bean>
2.定时器工厂 Bean
最后,您可以配置一个 TimerFactoryBean bean 来启动您的调度程序任务。
<bean class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref local="timerTask" />
</list>
</property>
</bean>
文件:Spring-Scheduler.xml
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="schedulerTask"
class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
<property name="targetObject" ref="runMeTask" />
<property name="targetMethod" value="printMe" />
</bean>
<bean id="runMeTask" class="com.mkyong.common.RunMeTask" />
<bean id="timerTask"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="timerTask" ref="schedulerTask" />
<property name="delay" value="1000" />
<property name="period" value="60000" />
</bean>
<bean class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref local="timerTask" />
</list>
</property>
</bean>
</beans>
运行它
package com.mkyong.common;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App
{
public static void main( String[] args )
{
ApplicationContext context =
new ClassPathXmlApplicationContext("Spring-Scheduler.xml");
}
}
没有代码需要调用调度程序任务, TimerFactoryBean 将在启动时运行您的调度任务。因此,Spring scheduler 将每 60 秒运行一次 printMe()方法,第一次执行时有 1 秒的延迟。
下载源代码
Download it – Spring-Scheduler-JDK-TimerExample.zipintegration scheduler spring timer