概述
Spring框架是分层的全栈式的轻量级开发框架,以IOC和AOP为核心,地址https://spring.io/
组成
- Data Access/Integration(数据访问/继承)
- JDBC模块:提供一个JDBC抽象层,大幅度减少了在开发中对数据库操作的编码
- ORM模块:对流行的对象关系映射API,包括JPA,JDO,Hibernate和iBatis提供集成层
- OXM模块:提供一个支持对象XML映射的抽象层实现,如JAXB,Castor,XMLBeans,JiBX,和XStream
- JMS模块:指JAVA消息服务,包含的功能为生产和消费的信息
- Transaction事务模块:支持编程和声明式事务管理实现特殊接口类,并为所有的POJO
- web模块
- WEB模块:提供了基本的web开发集成特性,例如文件上传,使用Servlet监听器的ioC容器初始化以及web应用上下文
- Servlet模块:包括Spring模型-视图-控制器实现web应用程序
- Struts模块:包括支持类的Spring应用程序,集成了经典的WEB-Servlet模块
- Core Container模块
- Beans模块:提供了BeanFactory,是工厂模式的经典实现,Spring将管理对象称为Bean
- Core模块:提供了Spring框架的基本组成部分,包括ioC和DI功能
- Context上下文模块:建立在核心和Beans模块的基础之上,它是访问定义和配置任何对象的媒介ApplicationContext接口是上下文模块的焦点
- Expression Language模块:是运行时查询和操作对象图的强大的表达式语言
- 其他模块
- AOP模块:提供了面向切面编程实现,允许自定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性
- Aspects模块:提供了与Aspectj的集成,是一个功能强大且成熟的面向切面编程框架
- Instrumentation模块:提供了类工具支持和类加载器的实现,可以在特定的应用服务器中使用
- Test模块:支持Spring模块,使用JUnit或TestNG测试框架
IOC概念
创建对象的权利,或者是控制位置,由JAVA代码转移到Spring容器,由Spring容器控制对象的创建,就是控制反转,Spring创建对象时,会读取配置文件中信息,然后使用反射给我们创建好的对象之后在容器中存储起来,当我们需要某个对象时,通过id获取对象即可,不需要我们自己去new
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/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.xsd">
<!-- 配置键名empDao,具体实现的类com.xpc.dao.impl.EmpDaoImpl--><bean id="empDao" class="com.xpc.dao.impl.EmpDaoImpl"></bean>
</beans>
// 测试
package com.xpc.test;import com.xpc.dao.EmpDao;
import com.xpc.dao.impl.EmpDaoImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class test1 {@Testpublic void testAddEmp(){EmpDaoImpl empDao = new EmpDaoImpl();empDao.addEmp();// 获取容器ApplicationContext a = new ClassPathXmlApplicationContext("spring.xml");EmpDao empDao1 = a.getBean("empDao", EmpDao.class);empDao1.addEmp();}
}
实现过程
- XML解析技术读取配置文件
<bean id="empDao" class="com.xpc.dao.impl.EmpDaoImpl"></bean>
- 反射技术获得实例化对象,放到容器中
// 获取类的字节码Class<?> aClass = Class.forName("com.xpc.dao.impl.EmpDaoImpl");// 获得实例化对象Object o = aClass.newInstance();// 放入map中map.put("empDao",o);
- 工厂模式Bean对象 getBean方法
javaBean
Bean管理就是spring对于JAVA程序中的对象的管理
- 对象的创建 IOC
不用自己new对象,解决对象创建问题 - 属性的赋值
DI 依赖的注入,创建属性时给对象的属性赋值,对象功能的实现往往要依赖于属性的值,那么给对象属性赋值就可以说成是依赖的注入
<?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:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- <bean id="user1" class="com.xpc.bean.User" name="user" lazy-init="false"></bean>--><bean id="user" class="com.xpc.bean.User"><property name="userId" value="1"></property></bean><bean id="user"><constructor-arg name="userId" value="111"></constructor-arg></bean><bean id="user" class="com.xpc.bean.User" p:userName="111" p:userId="111"></bean>
</beans>
- 读取属性配置文件
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 读取jdbc.properties配置--><context:property-placeholder location="classpath:jdbc.properties"/><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" ><property name="username" value="${jdbc_username}"></property><property name="password" value="${jdbc_password}"></property><property name="url" value="${jdbc_url}"></property><property name="driverClassName" value="${jdbc_driverClassName}"></property></bean>
</beans>
bean生命周期
- 通过构造器创建bean实例 执行构造器
- 为bean属性赋值 执行set方法
- 初始化bean 调用bean的舒适化方法,需要配置指定调用的方法
- bean的获取 容器对象gebean方法
- 容器关闭销毁bean 调用销毁方法,需要配置指定调用的方法
bean后置处理器
可以在bean实例化,配置以及其他初始化方法前后要添加一些自己的逻辑处理可以定义一个或者多个BeanPostProcessor接口实现类
实现接口
package com.xpc.beanProcesser;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanProcesser implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// bean 得到的内存中的类// beanNameSystem.out.println("初始化之前");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("初始化之后");return bean;}
}
xml中配置
<bean id="beanProcesser" class="com.xpc.beanProcesser.MyBeanProcesser"></bean>
注解
注解创建对象
注解类型
注解 | 作用 |
---|---|
@Component | 放在类上,告诉Spring当前类需要由容器实例化bean并放入容器中,该注解有三个子注解 |
@Service | 用于实例化service层bean |
@Controller | 用于实例化controller层bean |
@Repository | 用于实例化持久层Bean |
- 现在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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd
"><context:component-scan base-package="com.xpc.bean"/>
</beans>
- 需要实例化的类加上注解
package com.xpc.bean;import org.springframework.stereotype.Component;@Component
public class user {
}
- 测试
package com.xpc.test;import com.xpc.bean.user;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test1 {@Testpublic void test(){ClassPathXmlApplicationContext ca = new ClassPathXmlApplicationContext("applicationContext.xml");user user = ca.getBean("user", user.class);System.out.println(user);}
}
注解方式依赖注入
- 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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd
"><context:component-scan base-package="xpc"/>
</beans>
- 加载类
package xpc.dao.impl;import org.springframework.stereotype.Repository;
import xpc.dao.UserDao;@Repository
public class ImplA implements UserDao {@Overridepublic void add() {System.out.println("add A");}
}package xpc.dao.impl;import org.springframework.stereotype.Repository;
import xpc.dao.UserDao;@Repository
public class ImplB implements UserDao {@Overridepublic void add() {System.out.println("add B");}
}
- 配置依赖注入
package xpc.service.impl;import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import xpc.dao.UserDao;
import xpc.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;@Service
public class UserImpl implements UserService {@Autowired@Qualifier(value = "implA")private UserDao userDao;@Overridepublic void add() {System.out.println("add UserImpl");userDao.add();}
}
- 测试
package com.xpc.test;import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import xpc.service.impl.UserImpl;public class Test1 {@Testpublic void test1(){ClassPathXmlApplicationContext ca = new ClassPathXmlApplicationContext("applicationContext2.xml");UserImpl userImpl = ca.getBean("userImpl", UserImpl.class);userImpl.add();// add UserImpl// add A}
}
@Autowired 根据类型到容器中找对应的对象,找到后给当前属性赋值 ,不依赖SET方法,配合@Qualifier可以指定名称注入对象
@Resource
- 属性赋值
- 静态赋值
package xpc.service.impl;import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import xpc.dao.UserDao;
import xpc.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;@Service
public class UserImpl implements UserService {@Autowired@Qualifier(value = "implA")private UserDao userDao;@Value("静态赋值名字")public String name;@Overridepublic void add() {System.out.println("add UserImpl");userDao.add();}
}
- 动态赋值
#新建配置文件name.properties
sname=动态赋值
<!-- 读取配置文件-->
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd
"><context:property-placeholder location="classpath:name.properties"/><context:component-scan base-package="xpc"/>
</beans>
package xpc.service.impl;import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import xpc.dao.UserDao;
import xpc.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;@Service
public class UserImpl implements UserService {@Autowired@Qualifier(value = "implA")private UserDao userDao;@Value("${sname}")public String name;@Overridepublic void add() {System.out.println("add UserImpl");userDao.add();}
}
AOP 切面编程
AOP切面编程可以帮助我们在不修改现有代码的情况下,对程序的功能进行扩展,往往用于实现日志处理,权限控制,性能检测,事务控制等AOP实现的原理就是动态代理,再有接口的情况下,使用JDK动态代理,在没有接口情况下使用cglib动态代理
概念
- 连接点
可以被增加的方法叫做连接点 - 切入点
实际增强的方法叫切入点 - 通知Advice
实际增强的逻辑部分称为通知(增强的功能) - 目标对象(被增强功能的对象)
织入Advice的目标对象 - 切面Aspect
表现为功能相关的一些advice方法放在一起声明组成一个Java类 - 织入WEaving
创建代理对象并实现功能增强的声明并运行过程
切入表达式
语法结构:execution([权限修饰符][返回值类型][类的全路劲方法][方法名][参数列表])
package com.xpc.aspect;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect
@Component
public class DaoAspect {// 定义一个公共方法@Pointcut("execution(* com.xpc.dao.*.add*(..))")public void addPointCut(){}// 执行之前@Before("addPointCut()")public void methodBefore(){System.out.println("methodBefore");}// 执行之后@After("addPointCut()")public void methodAfter(){System.out.println("methodAfter");}// 方法返回值@AfterReturning(value = "addPointCut()",returning = "res")public void methodAfterReturning(JoinPoint joinPoint,Object res){// joinPoint 参数// res 返回值System.out.println(res);System.out.println("methodAfterReturning");}// 方法出异常执行@AfterThrowing(value = "addPointCut()",throwing = "exc")public void methodAfterThrowing(Exception exc){System.out.println(exc);}// 环绕通知 之前和之后都执行@Around("addPointCut()")public Object methodAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("around Before");// proceedingJoinPoint 表示切点,proceed表示执行切点方法,默认返回一个objectObject proceed = proceedingJoinPoint.proceed();System.out.println("around After");return proceed;}
}
spring事务
JdbcTemplate概述
JdbcTemplate是spring框架中提供的一个对象,用来对Jdbc AP进行简单封装
- 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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd
"><context:property-placeholder location="classpath:jdbc.properties"/><context:component-scan base-package="com.xpc"/>
<!-- 配置德鲁伊连接池--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="username" value="${jdbc_user}"/><property name="password" value="${jdbc_password}"/><property name="url" value="${jdbc_url}"/><property name="driverClassName" value="${jdbc_driver}"/></bean>
<!-- 配置JDBCTemplate对象,并向里面注入DataSource--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean>
</beans>
- 实现service层并关联dao层
- 实现数据库存储对象
package com.xpc.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@AllArgsConstructor
@NoArgsConstructor
@Data
public class Emp implements Serializable {private int EMPNO;private int DEPTNO;private String ENAME;private String IOB;
}
- 实现dao层
package com.xpc.dao.impl;import com.xpc.dao.EmpDao;
import com.xpc.pojo.Emp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;@Repository
public class MyEmpDao implements EmpDao {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic int findEmpCount() {String sql = "select count(1) from emp";Integer integer = jdbcTemplate.queryForObject(sql, Integer.class);return integer;}@Overridepublic Emp findByEmp(int empno) {String sql = "select * from emp where EMPNO = ?";BeanPropertyRowMapper<Emp> rowMapper = new BeanPropertyRowMapper<>(Emp.class);Emp emp = jdbcTemplate.queryForObject(sql, rowMapper, empno);return emp;}
}
spring_MVC
M:model 模型层 DAO封装 mybatis
V:view 视图层 HTML
C:controller 控制层 Servlet封装 SpringMVC
@RequestMapping控制请求参数
package com.xpc.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class MyController {@RequestMapping("/MyCon.do")public String test(){return "sucess";}@RequestMapping(value = "/MyCon2.do",params = {"username!=root","passworld"})public String test2(){return "sucess";}@RequestMapping(value = "/MyCon.do",headers = "Accpet-Encoding=gzip")public String test3(){return "sucess";}
}
获取请求参数
package com.xpc.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@RestController
public class TestDataController {/*** 使用传统httpServletRequest获取参数*/@RequestMapping("/getParamByRequest.do")public String getParams1(HttpServletRequest req, HttpServletResponse resp){String username = req.getParameter("username");return "";}/*** 通过springMVC获取参数*/@RequestMapping("/getParamByArgName.do")public String getParams12(String username){System.out.println(username);return "";}
}
接收参数
- POJO接收参数
package com.xpc.pojo;import java.io.Serializable;// 建立对应实体类
public class Person implements Serializable {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}
package com.xpc.controller;import com.xpc.pojo.Person;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ReceiveDataController {@RequestMapping("/getPojoData")public String getDataByPojo(Person p){// 传参进去 自动封装属性到 pSystem.out.println(p);return "success";}
}
- 日期类型转换
@DateTimeFormat 可以用于函数和对象上,用于解释用那种格式转换日期
package com.xpc.controller;import com.xpc.pojo.Person;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ReceiveDataController {@RequestMapping("/getPojoData")public String getDataByPojo(@DateTimeFormat(pattern = "yyyy-MM-dd")Data birthdate){/*** 告诉spring以这种 yyyy-MM-dd 格式解析日期*/System.out.println(birthdate);return "success";}
}
- List,map集合接收参数
package com.xpc.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.util.ArrayList;
import java.util.Map;@AllArgsConstructor
@NoArgsConstructor
@Data
public class Person implements Serializable {private String name;private Data data;private ArrayList<Pet> petList;private Map<String,Pet> petMap;
}
- 接收乱码
<filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filer-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filer-mapping>
响应
- 请求转发和响应重定向
package com.xpc.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@RestController
public class ReceiveDataController {/*** 紧耦合*/@RequestMapping("demo1")public void changePage(HttpServletRequest req, HttpServletResponse resp) throws Exception {// 请求转发req.getRequestDispatcher("/forward.jsp").forward(req,resp);// 响应重定向resp.sendRedirect(req.getContextPath()+"/redirect.jsp");}/*** 返回字符串告诉要转发的路径* 通过关键字控制*/@RequestMapping("demo2")public String changePage(){// 如果关键字是forward,可以省略// '/' 表示当前路径下
// return "forward:/forwardPage.jsp";return "redirect:/redirectPage.jsp";}// 视图转发@RequestMapping("demo3")public View changePage3(HttpServletRequest req){View v = null;v= new InternalResourceView("forward.jsp");v= new RedirectView(req.getContextPath()+"redirect.jsp");return v;}@RequestMapping("demo5")public ModelAndView changPage5(){ModelAndView mv = new ModelAndView();mv.setView(new InternalResourceView("forward:forwardPage.jsp"));return mv;}
- 响应JSON数据
引入依赖
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.2</version></dependency>
// ResponseBody表示返回值不跳转,以JSON格式解析@ResponseBody@RequestMapping("demo6")public Pet testAjax(){Pet pet = new Pet("tom");return pet;}
拦截器
Spring MVC中的拦截器类似于Servlet中的过滤器,它主要作用是拦截用户请求并作相应处理,比如可以进行权限验证,记录请求信息的日志,判断用户是否登录
- 使用拦截器,需要对拦截器进行定义和配置
- 通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类
- 通过实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口实现类来定义
- 拦截器和过滤器区别
- 拦截器SpringMVC的,而过滤器是servlet的
- 拦截器不依赖于servlet容器,由spring容器初始化
- 拦截器只能对action请求起作用,而过滤器则可以对所有请求起作用
- 拦截器可以访问action上下文,值栈里的对象,而过滤器不能
- 在action的生命周期中,拦截器可以多次被调用,而过滤器只在初次被调用
- 拦截器可以获取IOC容器中的各个bean,而过滤器不方便,在拦截器中注入service,可以调用业务逻辑
package com.xpc.interceptor;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MyInterceptor implements HandlerInterceptor {/**** @param request current HTTP request* @param response current HTTP response* @param handler chosen handler to execute, for type and/or instance evaluation* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 请求到达handler之前request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");request.getHeader("auth");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// 处理单元返回ModelAndView时候拦截}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 渲染完毕但是还没给浏览器响应数据}
}