Spring框架基础
注册 PropertyPlaceholderConfigurer
Spring 2.5 之后: 可通过 context:property-placeholder 元素简化:
中添加 context Schema 定义
在配置文件中加入如下配置:
IOC 容器中 Bean 的生命周期方法
Spring IOC 容器可以管理 Bean 的生命周期, Spring 允许在 Bean 生命周期的特定点执行定制的任务.
Spring IOC 容器对 Bean 的生命周期进行管理的过程:
通过构造器或工厂方法创建 Bean 实例
为 Bean 的属性设置值和对其他 Bean 的引用
调用 Bean 的初始化方法
Bean 可以使用了
当容器关闭时, 调用 Bean 的销毁方法
在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化和销毁方法.
注解
@Component: 基本注解, 标识了一个受 Spring 管理的组件
@Respository: 标识持久层组件
@Service: 标识服务层(业务层)组件
@Controller: 标识表现层组件
在 classpath 中扫描Bean
当在组件类上使用了特定的注解之后, 还需要在 Spring 的配置文件中声明 context:component-scan :
base-package 属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类.
当需要扫描多个包时, 可以使用逗号分隔.
如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern 属性过滤特定的类,示例:
<context:component-scan base-package="com.et">
<context:include-filter type=“annotation” expression=“org.*.stereotype.Service"/>
<context:exclude-filter type="assignable" expression="com.et.bean.Address"/>
</context:component-scan>
context:include-filter 子节点表示要包含的目标类
context:exclude-filter 子节点表示要排除在外的目标类
classpath 中扫描组件
context:include-filter 和 context:exclude-filter 子节点支持多种类型的过滤表达式:
组件装配
context:component-scan 元素还会自动注册 AutowiredAnnotationBeanPostProcessor 实例, 该实例可以自动装配具有 @Autowired 和 @Resource 、@Inject注解的属性.
使用 @Autowired 自动装配 Bean
@Autowired 注解自动装配具有兼容类型的单个 Bean属性
构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired 注解
默认情况下, 所有使用 @Authwired 注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Authwired 注解的 required 属性为 false
默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时, 通过类型的自动装配将无法工作. 此时可以在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参标注 @Qualifiter 已指定注入 Bean 的名称
@Authwired 注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配.
@Authwired 注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean.
@Authwired 注解用在 java.util.Map 上时, 若该 Map 的键值为 String, 那么 Spring 将自动装配与之 Map 值类型兼容的 Bean, 此时 Bean 的名称作为键值
使用 @Resource 或 @Inject 自动装配 Bean
Spring 还支持 @Resource 和 @Inject 注解,这两个注解和 @Autowired 注解的功用类似
@Resource 注解要求提供一个 Bean 名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为 Bean 的名称
@Resource是JDK自带的注解,耦合度低
@Inject 和 @Autowired 注解一样也是按类型匹配注入的 Bean, 但没有 reqired 属性
建议使用 @Autowired 注解
mavenMVC 加注解练习
pom文件装配
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.20.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.20.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.2</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>
html
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="emp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style type="text/css">
table{
width:60%;
border-collapse: collapse;
text-align: center;
}
div {
width:100%;
margin-left:15%;
}
h1{
text-align: center;
}
table td{
border:1px solid green;
}
span{
padding-left:20px;
padding-right:20px;
}
</style>
</head>
<body>
<h1>员工信息查询表</h1>
<div>
<form action="${pageContext.request.contextPath}/listEmp">
<p>员工姓名:<input type="text" name="ename" value="${requestScope.ename}">
<input type="submit" value="查询">
</form>
<table>
<tr>
<td>员工编号</td>
<td>员工姓名</td>
<td>职位</td>
<td>薪资</td>
<td>部门编号</td>
</tr>
<emp:forEach var="eml" items="${requestScope.pb.data}">
<tr>
<td>${eml.empno}</td>
<td>${eml.ename}</td>
<td>${eml.job}</td>
<td>${eml.sal}</td>
<td>${eml.deptno}</td>
</tr>
</emp:forEach>
</table>
<p>
<a href="listEmp?ename=${param.ename}&&curPage=${requestScope.pb.prePage}">上一页</a>
<emp:forEach var="i" begin="1" end="${requestScope.pb.totalPage}" step="1">
<a href="listEmp?ename=${param.ename}&curPage=${i}">${i}</a>
</emp:forEach>
<span>总页数:${requestScope.pb.totalPage} </span>
<span>当前页:${requestScope.pb.curPage} </span>
<span>总条数:${requestScope.pb.total} </span>
<a href="listEmp?ename=${param.ename}&curPage=${requestScope.pb.nextPage}">下一页</a>
</div>
</body>
</html>
contoller层
@WebServlet(urlPatterns="/listEmp")
public class EmpServlet extends HttpServlet{
@Autowired
private EmpService service;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String ename=req.getParameter("ename");
String curPage=req.getParameter("curPage");
String pageNumber=req.getParameter("pageNumber");
try {
service=MysqlUtil.cpac.getBean(EmpService.class);
PageLimit<Emp> pb = service.queryEmp(ename,curPage,pageNumber);
req.setAttribute("pb", pb);
req.getRequestDispatcher("/emp.jsp").forward(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
dao层
public interface EmpDao {
public int countEmp(String ename) throws Exception;
List<Emp> queryEmp(String ename,int startIndex,int pageNumber) throws Exception;
}
public class EmpDaoImpl implements EmpDao{
/**
* 分页展示
*/
public int countEmp(String ename) throws Exception {
QueryRunner qr=new QueryRunner(MysqlUtil.bds);
List<Emp> list;
String sql="select count(*) as myCount from emp";
if(StringUtils.isNotEmpty(ename)) {
sql+=" where ename like '%"+ename+"%'";
}
Map map=(Map) qr.query(sql, new MapHandler());
return Integer.parseInt(map.get("myCount").toString());
}
/**
* 查询emp表中的数据
*/
@Override
public List<Emp> queryEmp(String ename,int startIndex,int pageNumber) throws Exception {
QueryRunner qr=new QueryRunner(MysqlUtil.bds);
List<Emp> list;
String sql="select empno,ename,job,sal,deptno from emp";
if(StringUtils.isNotEmpty(ename)) {
sql+=" where ename like '%"+ename+"%'";
}
sql+=" limit "+startIndex+","+pageNumber;
list = (List<Emp>) qr.query(sql, new BeanListHandler(Emp.class));
return list;
}
dbutils 数据库层
public class MysqlUtil {
public static BasicDataSource bds;
public static ClassPathXmlApplicationContext cpac;
static {
Properties pro=new Properties();
cpac=new ClassPathXmlApplicationContext("classpath:prop.xml");
bds=(BasicDataSource) cpac.getBean("dataSource");
}
}
分页展示
public class PageLimit<T> {
/**
*
* @param curPage 当前页
* @param pageNumber 每页显示条数
* @param total 总共条数
*/
public PageLimit(int curPage, int pageNumber,int total) {
//计算上一页
this.prePage=(curPage==1 ? 1 : curPage-1);
//计算总页数
this.totalPage=(total%pageNumber==0 ? total/pageNumber : total/pageNumber +1);
//计算下一页
this.nextPage=(curPage==totalPage ? totalPage : curPage+1);
//当前页的索引
this.startIndex=(curPage-1)*pageNumber;
this.total=total;
this.curPage=curPage;
this.pageNumber=pageNumber;
}
/**
* 当前页 查询的默认当前页=1
* 页面传递的参数
*/
private int curPage;
/**
* 每页显示数据, 默认数据8条
* 页面传递的参数
*/
private int pageNumber=2;
/**
* 上一页
* 根据当前页计算
* if curPage==1 prePage=1 当前页是1的情况下 ,上一页是1
* if curPage>1 prePage=curPage-1 当前页大于1的情况下 ,上一页是当前页-1
*/
private int prePage;
/**
* 下一页
* if curPage==totalPage nextPage=totalPage 当前页是最后一页的情况下 ,下一页是最后一页
* if curPage<totalPage nextPage=curPage+1 当前页小于最后一页的情况下 ,下一页是最后一页+1
*/
private int nextPage;
/**
* 总共多少页
* 总条数tatal/每页显示的数据 pageNumber
* total%pageNumber==0 ? total/pageNumber : total/pageNumber +1
*/
private int totalPage;
/**
* 总共多少条
* 数据库查询
*/
private int total;
/**
* 开始索引
* (startIndex-1)*pageNumber
*/
private int startIndex;
public int getStartIndex() {
return startIndex;
}
public void setStartIndex(int startIndex) {
this.startIndex = startIndex;
}
/**
* 转载当前页的数据
*/
private List<T> data;
public int getCurPage() {
return curPage;
}
public void setCurPage(int curPage) {
this.curPage = curPage;
}
public int getPageNumber() {
return pageNumber;
}
public void setPageNumber(int pageNumber) {
this.pageNumber = pageNumber;
}
public int getPrePage() {
return prePage;
}
public void setPrePage(int prePage) {
this.prePage = prePage;
}
public int getNextPage() {
return nextPage;
}
public void setNextPage(int nextPage) {
this.nextPage = nextPage;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public List<T> getData() {
return data;
}
public void setData(List<T> data) {
this.data = data;
}
}
属性bean
public class Emp {
private String empno;//员工编号
private String ename;//员工姓名
private String job;//职位
private String hiredate;//入职时间
private String sal;//薪资
private String deptno;//部门编号
public String getEmpno() {
return empno;
}
public void setEmpno(String empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public String getHiredate() {
return hiredate;
}
public void setHiredate(String hiredate) {
this.hiredate = hiredate;
}
public String getSal() {
return sal;
}
public void setSal(String sal) {
this.sal = sal;
}
public String getDeptno() {
return deptno;
}
public void setDeptno(String deptno) {
this.deptno = deptno;
}
}
service层
public interface EmpService {
public PageLimit<Emp> queryEmp(String ename,String curPage,String pageNumber) throws Exception;
}
public class EmpServiceImpl implements EmpService{
@Autowired
private EmpDao dao;
public PageLimit<Emp> queryEmp(String ename,String curPage,String pageNumber) throws Exception{
//第一次访问 没有当前页
if(StringUtils.isEmpty(curPage)) {
curPage="1";
}
if(StringUtils.isEmpty(pageNumber)) {
pageNumber="2";
}
//转换成int 类型
int curPageIn=Integer.parseInt(curPage);
int pageNumberIn=Integer.parseInt(pageNumber);
int total=dao.countEmp(ename);
PageLimit<Emp> pb=new PageLimit<>(curPageIn,pageNumberIn,total);
List<Emp> queryEmp = dao.queryEmp(ename,pb.getStartIndex(),pb.getPageNumber());
pb.setData(queryEmp);
return pb;
}
}
properties
jdbcDriver=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/unit02
jdbcUsername=root
jdbcPassword=******
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<context:component-scan base-package="com"></context:component-scan>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbcDriver}"></property>
<property name="url" value="${jdbcUrl}"></property>
<property name="username" value="${jdbcUsername}"></property>
<property name="password" value="${jdbcPassword}"></property>
</bean>
</beans>