- 监听器
- 原理
- org.springframework.web.context.ContextLoaderListener中
- this.contextLoader.initWebApplicationContext(event.getServletContext());
- 加载Spring 的配置文件 ,加载Application内置对象中
- initWebApplicationContext方法中
- this.context = createWebApplicationContext(servletContext, parent);
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
- 创建并存储spring的application内置对象到ServletContext中,属性名称是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
- createWebApplicationContext方法中
- wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM));
- 该类文件中有:public static final String CONFIG_LOCATION_PARAM = “contextConfigLocation”;
- 获得web.xml中配置的context-param初始化参数:contextConfigLocation的内容,并加载spring配置文件
- 使用
- servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
- ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext)
- properties
- spring xml配置文件中使用properties配置的属性
- 配置一个bean的class类是org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer的单例bean
- <property name=“locations” value=“classpath:public.properties” > - <array> - <value>classpath:conn.properties</value> - 或
- <property name=“location” value=“classpath:conn.properties” /> - xml文件中用”${driver}“的方式引用properties中配置的属性
- java类中用spring的注解注入properties配置的属性
- 要求必须是spring管理的类
- bean中的class类换成org.springframework.beans.factory.config.PropertiesFactoryBean
- id=“Xxx”其它相同
- java类的属性或set方法上添加注解:
- @Value(”#{public.basePath}#{public.filePath}”)
- 其中public 是上面配置的bean的id(xml文件中注入属性的话用不到id,所以没有配置)
- ’#{}‘代表引用属性
- ’.’可以用’[]‘代替,如public[basePath]
- 字符串的拼接可以用+连接
- 第一次配置@Value的时候不会成功,改一次值再试就可以了
- bean
- 创建bean的顺序
- 生命周期
- 配置中定义
- 初始化
- 配置文件中init-method
- 实现org.springframework.beans.factory.InitializingBean接口
- 调用
- 销毁
- 配置文件中destroy-method
- 实现org.springframework.bean.factory.DisposeableBean
- scope
- 默认singleton
- prototype # 每次产生新对象
- singleton # 单例
- request # 一个请求一个对象,只在ApplicationContext下有效
- session # 一个session一个对象,只在ApplicationContext下有效
- global-session # 一个全局session一个对象, 只在ApplicationContext下有效
- 内部bean
- <property>或<constructor-arg>中定义的<bean>,通常匿名 - 注入对象
- <list> - <set> - <map> - <props> # 键值都只能是string类型 - 自动装配
- 方式
- no # 不自动装配,通过ref属性指定
- byName
- byType
- constructor
- autodetect
- 写法
- <bean>属性autowire=“byName” - @Autowired
- 类型自动装配
- 加上@Qualifier(value=“a”)
- @Resource(name=“a”)注解的name装配
- byName装配
- byType装配
- 配置
- <?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=”
- <bean - id=“userDaoID”
- name=""
- class=“cn.itcast.javaee.spring.bean.life.UserDao”
- init-method=“getSession”
- destroy-method=“closeSession”
- factory-method=“getUserDao”
- scope=“singleton”
- lazy-init=“false”
- parent=“userDaoID”
- abstract=“true”
- autowire=“no”>
- <constructor-arg type=“java.lang.Integer” index ref> - <value>2013</value> - <constructor-arg type=“java.lang.Double”> - <value>6000</value> - <property name=“name” value=“aa”></property> - <property name=“name” ref=“dateID” /> - <property name=“telSet”> - <set> - <value>11</value> - <property name=“cityList”> - <list> - <value></value> - <property name=“telCityMap”> - <map> - <entry key=""> - <value></value> - <property name=""> - <props> - <prop key=""></prop> - 标签、属性分析
- bean标签:代表一个JavaBean
- 多个JavaBean配置时,先配置的先创建,先创建的后销毁
- id:该JavaBean的唯一标识
- name:可以和id一样用,但是name可以设置”/a”来绑定路径
- class:该JavaBean的类路径
- init-method:创建该JavaBean时运行的其中的方法
- destroy-method:销毁该JavaBean时运行的其中的方法
- ClassPathXmlApplicationContext类的实例不监听销毁方法
- 用AbstractApplicationContext中的close()与registerShutdownHook()方法
- close()直接马上销毁,registerShutdownHook()方法会注册关闭钩子,监听容器的销毁
- factory-method:创建该Bean的函数
- 得到接口实现类的方法
- 1.通过实现类的无参构造器 # 没有factory-method属性
- 2.没有无参构造器时,工厂静态方法创建实例
- <bean id=“userDaoID” factory-bean=“daoFactoryID” factory-method=“getUserDao”> - class中的内容是工厂类,而非UserDao类,factory-method是工厂类中返回UserDao类的静态方法
- 3.没有无参构造器时,工厂非静态方法创建实例
- <bean id=“daoFactoryID” class=“cn.itcast.javaee.spring.bean.create.type3.DaoFactory”> - <bean id=“userDaoID” factory-bean=“daoFactoryID” factory-method=“getUserDao”> - 先实例化工厂(Spring 加载本xml文件默认实例化),然后静态方法的配置即可
- scope:作用域
- 1.singleton(单例)是默认值,是单例的,会调用init destory方法
- 2.prototype(原型)每次创建一个实例, 调用init方法,但不调用destory方法(实例的维护 :javase程序交给jvm,javaee程序交给服务器)
- lazy-init
- 1.false:为启动容器时立即创建一个实例 # singleton与prototype模式都会创建
- 2.true:启动时不加载,获取时创建
- parent: 继承一个Spring bean(包含其中的所有属性)
- javaBean类中不必有实际的继承关系(但是有继承关系则必要配置parent)
- abstract=“true” : 配置此Bean为抽象Bean
- autowire=“no”:自动装配,只能装配关联属性
- 还可以进行注解装配
- byName 装配时根据bean中的每个属性名从spring中找id同名的bean,通过setter方法注入到该属性中
- byType 根据bean中的每个属性的类型找到spring中映射该类型的bean进行装配,通过setter方法注入到该属性中
- constructor 找满参构造器装载,构造器中的参数以byType方式注入
- autodetect 先找构造器装载,再set方法注入。但实际使用中只能set方法注入
- no 不注入
- 可以配置init-method与destroy-method属性来配置该bean创建和销毁时执行的方法
- 注入值 # 通过setter方法注入值
- <constructor-arg type=“java.lang.Integer” index ref> - <value>2013</value> # 传入构造方法参数注入值,,位置不能颠倒,不调用setter方法 - type是注入参数的类型,index是参数的标号,从0开始,ref是引用类型,有引用类型时不用标签
- <property name=“name” value=“aa”/> # 基本类型直接赋值(包括包装类型与String) - <property name=“name” ref=“dateID”/> # 引用类型,dateID是一个Spring Bean - 可以直接引用Spring Bean 的id
- <set> - <value></value> # set集合 - <list> - <value></value> # list集合 - <map> - <entry key=""> - <value></value> # map集合 - 集合的值均可配置引用类型
- <property name=""> - <props> - <prop key=""></prop> # 属性类型,只能配置基本类型 (包括包装类型与String)- AOP
- 实现 # 基于Aspectj
- 原理
- 启动容器时,创建目标对象与代理对象
- <aop:config/>加载完时,通过cglib创建目标对象的代理对象,运行时产生 - 程序员-代理对象-代理方法-目标对象-目标方法-代理对象
- 使用
- 写类文件
- 1.jar包 aspectjweaver.jar/aspectjrt.jar/cglib-nodep-2.1_3.jar(动态代理包)
- 2.配置xml文件头,保留aop
- <bean id class/> # 目标对象 - <bean id=“serviceBeanID” class /> # 配置增强对象 - <aop:config> # 相当于创建了代理对象 - <aop:pointcut id=“xxxx” expression="" /> # 切入点表达式:expression=“execution(public void addUser() throws java.lang.Exception)” - 可以写成execution(public void 类名.()),表示匹配所有方法
- execution( (..)) 第一个是返回值,第二个*是方法,..表示参数不限
- 可以声明抛异常
- 条件命名为xxxx,升级连接点到切入点
- <aop:aspect ref=“serviceBeanID”> - <aop:before method=“writeLog” pointcut-ref=“xxxx”/> # 前置增强,method是注入的方法,xxxx是增强的条件,只能写一个方法 - <aop:after/> - <aop:after-returning/> # 方法返回后执行 - <aop:after-throwing/> # 抛出异常时执行 - <aop:around/> # 环线,执行目标方法前、后都执行,出错则之后的函数不执行 - public void both(ProceedingJoinPoint pjp){ # ProceedingJoinPoint是连接代理对象 与目标对象的桥梁
- open();
- pjp.proceed(); # 执行目标代码
- close();
- }
- 目标方法出错,后置增强仍然执行,after-throwing执行,前置增强不执行,after-returning不执行
- <aop:advisor advice-ref=“txAdvice” pointcut-ref=“xxxx”/> # 配置事务的切面 - 切入点表达式
- execution(方法的修饰符 方法的返回值类型 方法所属的类 方法名 方法中参数列表 方法抛出的异常)
- 方法的修饰符: 支持通配符*,可省略
- 方法的返回值类型:支持通配符*,表示所有返回值,不可省
- 方法所属的类: 支持通配符*,可省略
- 方法名: 支持通配符*,表示所有方法,不可省
- 方法中参数列表: 支持通配符*,不可省
- *表示【一个】任意类型的参数
- ..表示零个或一个或多个任何类型的参数【提倡】
- execution(方法的返回值类型 方法名(方法中参数列表)) # 一般形式
- 例如:
- execution(public void add()throws Exception)
- execution(public void add(..)throws Exception)
- execution(public void add(*)throws Exception)
- execution(* cn.itcast.web.spring.aop.UserDao.add(..))
- execution(* add()throws Exception)
- execution(public void *(..)throws Exception)
- execution(public void a*(..)throws Exception):方法名以a字符开始
- execution(public void *d(..)throws Exception):方法名以d字符结束
- execution(* add())
- execution(* *(..))
- 切点方法的编写
- public void Xxx(JoinPoint joinPoint){
- joinPoint.getTarget(); # 获取目标对象
- joinPoint.getSignature(); # 获取当前连接点的方法信息
- joinPoint.getArgs()[0]; # 获取当前连接点的第一个参数
- ..
- }
- public Goods Yxx(ProceedingJoinPoint joinPoint){
- Object object = joinPoint.proceed(); # 得到连接点的返回值
- ..
- return goods; # 本切面返回的数据会作为切点返回的数据返回给调用它的函数
- }
- DAO
- 使用
- 1.xml文件中
- <!— 配置C3P0连接池 ⇒ - <bean id=“comboPooledDataSourceID” class=“com.mchange.v2.c3p0.ComboPooledDataSource”> - <property name=“driverClass” value=“com.mysql.jdbc.Driver”/> - <property name=“jdbcUrl” value=“jdbc:mysql://127.0.0.1:3306/spring”/> - <property name=“user” value=“root”/> - <property name=“password” value=“root”/> - <property name=“initialPoolSize” value=“60”/> - <property name=“acquireIncrement” value=“5”/> - </bean> - <!— 配置JdbcTemplate ⇒ - <bean id=“jdbcTemplateID” class=“org.springframework.jdbc.core.JdbcTemplate”> - <property name=“dataSource” ref=“comboPooledDataSourceID”/> - </bean> - <!— 配置UserDao ⇒ - <bean id=“userDaoID” class=“dao.UserDao”> - <property name=“jt” ref=“jdbcTemplateID”/> - </bean> - 2.Dao中
- private JdbcTemplate jt;
- addUser()
- String sql = "";
- Object [] params = {user.getUsername(),user.getPassword()}
- jt.update(sql,params);
- 批量:
- for(int i = 0; i < ids.length; i++){
- }
- jt.batchUpdate(sqls);
- 查询一个
- return (User)jt.queryForObject(sql,params,new RowMapper(){
- public Object mapRow(ResultSet rs,int rowNum){ # rs是查询出来的结果集,rowNum是结果集的行号,从0开始
- Integer id = rs.getInt(“id”);
- User user = new User(id);
- return user;
- }
- });
- 查询多个 # query方法把RowMapper帮助类中返回的user分别加入到list中,返回一个list
- list = jt.query(sql,new RowMapper(){
- public Object mapRow()
- })
- 分页
- String sql = “select * from users limit ?,?”;
- Object[] params = {0,3};
- jt.query(sql,params,new RowMapper(){
- 记录
- jt.queryForInt(sql);
- 事务
- TransactionInterceptor
- transactionManager # 指定事务治理类
- transactionAttributes # key方法名 value事务属性
- 注解
- @Transactional(propagation = Propagation.REQUIRED)
- 手写 # TransactionDefinition
- Public class BankServiceImpl implements BancService{
- Private BanckDao bankDao;
- private TransactionDefinition txDefinition;
- private PlatformTransactionManager txManager;
- public boolean transfer(Long fromId, Long toId, double amount) {
- TransactionStatus txStatus = txManager.getTransaction(txDefinition);
- boolean result = false;
- try {
- result = bankDao.transfer(fromId, toId, amount);
- txManager.commit(txStatus);
- } catch (Exception e) {
- result = false;
- txManager.rollback(txStatus);
- System.out.println(“Transfer Error!”);
- }
- return result;
- }
- }
- 手写 # TransactionTemplate
- public class BankServiceImpl implements BankService {
- private BankDao bankDao;
- private TransactionTemplate transactionTemplate;
- public boolean transfer(final Long fromId, final Long toId, final double amount) {
- return (Boolean) transactionTemplate.execute(new TransactionCallback(){
- public Object doInTransaction(TransactionStatus status) {
- Object result;
- try {
- result = bankDao.transfer(fromId, toId, amount);
- } catch (Exception e) {
- status.setRollbackOnly();
- result = false;
- System.out.println(“Transfer Error!”);
- }
- return result;
- }
- });
- }
- }
- 配置 # TransactionInterceptor
- <bean id=“transactionInterceptor” class=“org.springframework.transaction.interceptor.TransactionInterceptor”> - <property name=“transactionManager” ref=“transactionManager”/> - <property name=“transactionAttributes”> - <props> - <prop key=“transfer”>PROPAGATION_REQUIRED</prop> - </props> - </property> - </bean> - <bean id=“bankServiceTarget” class=“footmark.spring.core.tx.declare.origin.BankServiceImpl”> - <property name=“bankDao” ref=“bankDao”/> - </bean> - <bean id=“bankService” class=“org.springframework.aop.framework.ProxyFactoryBean”> - <property name=“target” ref=“bankServiceTarget”/> - <property name=“interceptorNames”> - <list> - <idref bean=“transactionInterceptor”/> - </list> - </property> - </bean> - 配置 # TransactionProxyFactoryBean
- <bean id=“bankServiceTarget” class=“footmark.spring.core.tx.declare.classic.BankServiceImpl”> - <property name=“bankDao” ref=“bankDao”/> - </bean> - <bean id=“bankService” class=“org.springframework.transaction.interceptor.TransactionProxyFactoryBean”> - <property name=“target” ref=“bankServiceTarget”/> - <property name=“transactionManager” ref=“transactionManager”/> - <property name=“transactionAttributes”> - <props> - <prop key=“transfer”>PROPAGATION_REQUIRED</prop> - </props> - </property> - </bean> - 配置 # tx空间
- <?xml version=“1.0” encoding=“UTF-8”?> - <beans xmlns=“http://www.springframework.org/schema/beans” - xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
- <!—配置c3p0连接池⇒ - <!— 配置JdbcTemplate类 ⇒ - <!— 配置Dao ⇒ - <!— 配置jdbc事务管理器 ⇒ - <bean id=“dataSourceTransactionManagerID” class=“org.springframework.jdbc.datasource.DataSourceTransactionManager”> - <property name=“dataSource” ref=“comboPooledDataSourceID”/> - </bean> - <!— 配置事务增强(服务对象) ⇒ - <tx:advice id=“txAdvice” transaction-manager=“dataSourceTransactionManagerID”> - <tx:attribute> - <tx:method name=“addUsers” # 可以用通配符”*users” - propagation=“required” # 传播行为:事务开始、结束的时间。required 保证方法执行时事务已开始,事务开始时不创建,没有开始时创建
- isolation=“default” # 隔离级别
- timeout=“-1” # 事务超时,-1代表不超时,用数据库底层的配置
- rollback-for:“java.lang.Exception” # 何时回滚
- read-only=“false” # 不只读
- name 方法名的匹配模式
- required : 外部存在事务,则加入外部事务,不存在则新建事务
- requires_new : 总是新建事务
- mandatory : 外部必须存在事务
- never : 外部不能存在事务
- supports : 外部存在则加入,不存在则不以事务方式运行
- not_supported : 总是非事务
- nested : 外部存在事务,嵌套执行,不存在则新建
- no-rollback-for 以逗号分隔异常,这些异常不会导致事务回滚
- rollback-for 导致事务回滚的异常
- <tx:attribute> - <!— 配置AOP ⇒ - <aop:config> - <aop:pointcut id=“xxxx” expression=“execution(public void *Users(..))”/> -
- 任意公共方法的执行:
- execution(public * *(..))
- 任何一个以“set”开始的方法的执行:
- execution(* set*(..))
- AccountService 接口的任意方法的执行:
- execution(* com.xyz.service.AccountService.*(..))
- 定义在service包里的任意方法的执行:
- execution(* com.xyz.service..(..))
- 定义在service包和所有子包里的任意类的任意方法的执行:
- execution(* com.xyz.service...(..))
- 定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行:
- execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))”)
- <!— 将事务代码切入点addUser()方法中,从而产生事务 ⇒ - <aop:advisor advice-ref=“txAdvice” pointcut-ref=“xxxx”/> - </aop:config>- spring mybatis
- 基础
- 与$
- 相当于解析成引号, 防止sql注入
- $变量引用, 不能防止sql注入,用于传入表名之类
- 特点
- Mapper接口
- 方法名与配置id相同
- 输入输出参数类型对应定义的parameterType类型和resultType类型
- 类路径是配置的namespace
- 缓存
- 基于PerpetualCache的HashMap
- 一级缓存
- 存在本地
- 作用域为session, session flush后清空
- 二级缓存
- 可定义存储服务
- 作用域为namespace
- 配置
- <cache/> - readOnly=“true” 时,缓存实例单例,false时返回缓存拷贝
- 更新
- create, update, delete后,作用域下所有select缓存clear
- 与hibernate区别
- 都通过SessionFactoryBuilder从配置生成SessionFactory, 再生成Session
- 都支持jdbc和jta
- mybatis可细致优化sql, hibernate移植性好
- mybatis学习成本低
- mybatis本身缓存不好,hibernate对象维护和缓存好
- hibernate dao层封开发简单(不用维护映射),crud方便
- 使用
- 编程
- 创建SqlSessionFactory
- 创建SqlSession
- 执行数据库操作
- session.commit()
- session.close()
- 导入ibatis jar包
- 配置文件
- SqlMap.properties # 属性名可以修改
- driver=oracle.jdbc.driver.OracleDriver
- url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
- username=root
- password=root
- SqlMapConfig.xml # 总配置文件
- <sqlMapConfig> - <properties recource=“SqlMap.properties”/> - <transactionManager type=“JDBC”> - <dataSource type=“SIMPLE”> - <property value=”${driver}” name=“JDBC.Driver”/> - <property value=”${url}” name=“JDBC.ConnectionURL”/> - <property value=”${username}” name=“JDBC.Username”/> - <property value=”${password}” name=“JDBC.Password”/> - </dataSource> - <sqlMap resource=“Student.xml”/> - </transactionManager> - </sqlMapConfig> - Student.xml # 映射xml文件
- <sqlMap> - <typeAlias alias=“Student” type=“com.Student”/> - <select id=“selectAllStudent” resultClass=“Student”> - select * from Student
- </select> - </typeAlias> - </sqlMap> - 辅助类Student.java # 要求有无参构造方法
- private sid = 0;
- private String name = null;
- private String major = null;
- private Date birth = null;
- private float score = 0;
- Xxx.java
- private static SqlMapClient sqlMapClient = null;
- static{
- Reader reader = Resources.getResourceAsReader(总配置文件);
- sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);
- reader.close();
- }
- public List queryAllStudent(){
- List studentList = sqlMapClient.queryForList(“selectAllStudent”);
- return studentList;
- }
- @Test
- public void testHere(){
- for(Student student: this.queryAllStudent()){
- System.out.println(student.getName);
- }
- }
- 配置
- sqlMapConfig.xml
- mybatis加载属性顺序
- properties中property中的属性
- properties中resource或url中的属性
- parameterType中传递一属性
- properties中配的属性会影响到mapper.xml中${}的sql拼接,因为都是ognl
- 配置标签
- properties
- settings
- ibatis有性能优化的参数,mybatis会自动调优,不用设置了
- typeAliases
- 针对parameterType和resultType指定的类型定义别名
- java.lang.Integer在mybatis中默认别名为int
- typeHandlers
- 类型处理器,jdbc类型和java类型的转换
- 一般mybatis提供的类型处理器够用了
- objectFactory
- plugins
- environments
- mappers
- mapper.xml
- 内容
- #{}接收简单类型, pojo的ognl属性注入
- ${}是字符串的拼接
- SELECT * FROM USER WHERE id=#{id}
- SELECT * FROM USER WHERE username LIKE ’%${value}%’
- 输入输出映射
- parameterType
- resultType
- 指定一条数据的类型,在java方法的返回类型中list或pojo来体现数据条数
- mybatis判断mapper代理中使用selectOne或者selectType
- pojo
- 返回字段可以是别名,但要与pojo中的属性名相同
- 如果有记录返回但没有pojo中匹配的属性名对应,则直接不创建该对象
- java类型
- hashmap
- key是字段的字,value是字段的值
- 多条数据时,list里面存hashmap
- resultMap
- 查询出来的字段名与pojo属性名不一致
- 定义resultMap
- 使用resultMap
- 动态sql
- <where> - <if> - sql片段
- <foreach> - 高级映射
- 缓存
- 逆向
- 要求
-
- mapper.xml中namespace 写mapper接口
- <mapper namespace=“com.otr.tea.mapper.UserMapper”> - 2. mapper.java中方法名与mapper.xml的statementid一致
-
- mapper.java中方法的输入类型与mapper.xml中的parameterType一致
- 由于传入的参数只有一个,所以用包装类型的pojo来传多个参数,不利于业务层的可扩展性
-
- mapper.java中方法的返回类型与mapper.xml中的resultType一致
- 机制
- 如果Mapper中返回类型为pojo, 则调用selectOne, 如果是List, 则调用selectList
- api
- sqlSessionFactory
- sqlSession # 是线程不安全的,因为它的类中有数据和属性
- # 是多例的,在方法中局部变量使用
- Executor # 执行器操作数据库(基本执行器,缓存执行器)
- mapped statement # 封装sql语句、输入参数、输出结果类型
- 例子
- InputStream is = Resources.getResourceAsStream(“SqlMapConfig.xml”);
- Resources是mybatis提供的资源加载类
- SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
- SqlSession sqlSession = factory.openSession();
- User user = sqlSession.selectOne(“test.findUserById”, 1);
- # selectList()
- insert(“test.insertUser”, user)
- sqlSession.commit();
- user.getId() 会主键返回
- mysql中LAST_INSERT_ID()在insert语句后接着执行可以得到刚刚自成的id
- sqlSession.close();
- 案例
- 返回id
- mysql
- <insert id=“insert” parameterType=“com.test.User” keyProperty=“userId” useGeneratedKeys=“true” > - oracle
- <insert id=“insert” parameterType=“com.test.User”> - <selectKey resultType=“INTEGER” order=“BEFORE” keyProperty=“userId”> - SELECT SEQ_USER.NEXTVAL as userId from DUAL
- </selectKey> - insert into user (user_id, user_name, modified, state)
- values (#{userId,jdbcType=INTEGER}, #{userName,jdbcType=VARCHAR},
- #{modified,jdbcType=TIMESTAMP}, #{state,jdbcType=INTEGER})
- </insert>- spring struts2
- 原理
- tomcat启动日志:没有整合时不能加载struts-plugin.xml(spring-struts-plugin.jar包中的配置文件 )
- struts中struts-default中常量配置加载com.opensymphony.xword2.ObjectFactory类作为默认struts创建action的类
- 加载后struts-plugin.xml 中 修改了常量为struts-spring-plugin中的类来创建struts的类,也就是整个struts2创建action类的类被更改了
- 整合
- jar包 struts2/lib/struts2-spring-plugin-2.3.1.1.jar # 为了在struts的xml配置文件中的class找spring 的容器
- 配置web.xml # \samples\petclinic\war\WEB-INF\web.xml目录下有示例
- <listener> # 监听器,web程序启动时加载spring bean - <listener-class>org.springframework.web.context.ContextLoaderListener - <context-param> # (可选)配置spring 配置文件的路径, - 从示例文件中查到,默认文件目录是/WEB-INF/applicationContext.xml(我们示例文件也是从源码/simple项目下的这个开头的文件中找的)
- <param-name>contextConfigLocation - <param-value>/WEB-INF/classes/struts2/xxx.xml - UserAction 中 # 不用值栈是因为通用性
- spring.xml # action类由spring 产生
- <bean id=“userActionID” class="" scope=“prototype”/> - struts2的配置文件中,替换class属性为spring beanid,其它一样
- 总结
- spring的web配置是由下向上,一个个依赖注入的过程
- comboPooledDataSourceID →
- localSessionFactoryBeanID →
- hibernateTemplateID →
- SysStaffDaoID →
- SysStaffServiceID →
- SysStaffActionID →
- struts.xml配置中的
- 最后给Dao中的方法加入事务
- spring mvc
- 原理
- DispatchServlet doService()捕获请求, doDispatch()用HandlerMapping映射url得到HandlerExcutionChain(执行链, 包括拦截器和handler)
- handler getHandlerAdapter得到适配器来处理handler, 返回ModelAndView
- HandlerAdapter分三类: Servlet、Controller, HttpRequest
- DispatchServlet用ViewResolver(视图解析器)解析ModelAndView成View
- ModelAndView是逻辑视图,DispatchServlet转化成视图View
- 返回View
- 与struts2区别
- spring mvc方法对应请求, struts2是类
- spring mvc请求是方法调用,struts2创建Action实例
- spring mvc用aop处理请求,struts2用独有的拦截器(interceptor)
- spring mvc入口是servlet, struts2入口是filter
- spring mvc集成ajax(@ResponseBody), struts2需要插件
- spring mvc验证支持JSR303, struts2不支持
- spring mvc与spring无缝
- spring mvc不需要配置
- 注解
- @RequestMapping # url映射
- @RequestBody # 转换参数到对象
- @ResponseBody # 返回对象转json
- 开启注解处理器
- springmvc.xml
- <mvc:annotation-driven> - 乱码问题
- post
- web.xml中配置CharacterEncodingFilter
- get
- tomcat配置文件修改项目编码
- new String(Request.getParameter(“a”).getBytes(“ISO8859-1”), “utf-8”)
- quartz
- 执行:ApplicationContext类加载后自动执行
- 导包:quartz-all.jar包 与 commons-collections.jar包 与 commons-logging.jar
- xml配置:
- <!— 任务类 ,其中有个叫execute的方法⇒ - <bean id=“myTaskID” class=“jee.quartz.MyTask”/> - <!— spring提供专用于定时任务类 ⇒ - <bean id=“methodInvokingJobDetailFactoryBeanID” class=“org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean”> - <!— 要定时执行的实例的spring bean id ⇒ - <property name=“targetObject”> - <ref bean=“myTaskID”/> - </property> - <!— spring bean中定时执行的方法 ⇒ - <property name=“targetMethod”> - <value>execute</value> - </property> - </bean> - <!— spring提供专用于任务频率类,给上面的任务指定频率 ⇒ - <bean id=“cronTriggerBeanID” class=“org.springframework.scheduling.quartz.CronTriggerBean”> - <property name=“jobDetail”> - <ref bean=“methodInvokingJobDetailFactoryBeanID”/> - </property> - <property name=“cronExpression”> - <value>0 0/1 * * * ?</value> - </property> - </bean> - <!— spring提供的专用于任务频率工厂类 ⇒ - <bean id=“schedulerFactoryBeanID” class=“org.springframework.scheduling.quartz.SchedulerFactoryBean”> - <property name=“triggers”> - <ref bean=“cronTriggerBeanID”/> - </property> - </bean> - 任务频率cronTriggerBean的配置:
- cron解析器:
- 反斜线(/)字符表示增量值。例如,在秒字段中“5/15”代表从第 5 秒开始,每 15 秒一次。
- 问号(?)字符和字母 L 字符只有在月内日期和周内日期字段中可用。问号表示这个字段不包含
- 具体值。
- 所以,如果指定月内日期,可以在周内日期字段中插入“?”,表示周内日期值无关紧要。字母
- L 字符是 last 的缩写。放在月内日期字段中,表示安排在当月最后一天执行。在周内日期字
- 段中,如果“L”单独存在,就等于“7”,否则代表当月内周内日期的最后一个实例。所以“0L”
- 表示安排在当月的最后一个星期日执行。
- 在月内日期字段中的字母(W)字符把执行安排在最靠近指定值的工作日。把“1W”放在月内
- 日期字段中,表示把执行安排在当月的第一个工作日内。
- 井号(#)字符为给定月份指定具体的工作日实例。把“MON2”放在周内日期字段中,表示把任
- 务安排在当月的第二个星期一。
- 星号(*)字符是通配字符,表示该字段可以接受任何可能的值。
- 顺序:秒 分 时 日 月 周 年(年可以忽略)
- 例子
- 0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
- 0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
- 0 0 12 ? * WED 表示每个星期三中午12点
- 0 0 12 * * ? 每天中午12点触发
- 0 15 10 ? * * 每天上午10:15触发
- 0 15 10 * * ? 每天上午10:15触发
- 0 15 10 * * ? * 每天上午10:15触发
- 0 15 10 * * ? 2013 2013年的每天上午10:15触发
- 0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟触发
- 0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发
- 0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
- 0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发
- 0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发
- 0 15 10 ? * MON-FRI 周一至周五的上午10:15触发
- 0 15 10 15 * ? 每月15日上午10:15触发
- 0 15 10 L * ? 每月最后一日的上午10:15触发
- 0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发
- 0 15 10 ? * 6L 2014-2018 2014年至2018年的每月的最后一个星期五上午10:15触发
- 0 15 10 ? * 63 每月的第三个星期五上午10:15触发
- 0/1 * * * * ? 每秒钟触发一次
- 0 0/1 * * * ? 每分钟解发一次
- 0 0 0/1 * * ? 每小时解发一次
- 远程调用
- rmi:remote message invoke
- 服务端
- 1.自定义接口IServer,自定义抽象方法int rax(int)
- 2.写接口实现类ServerImpl
- 3.配置spring.xml 文件
- <!— 服务端实现类 ⇒ - <bean id=“serverImplID” class=“jee.server.ServerImpl”/> - <!— spring提供的专用于RMI服务端注册器 ⇒ - <bean id=“rmiServiceExporterID” class=“org.springframework.remoting.rmi.RmiServiceExporter”> - <property name=“serviceInterface”> - <value>jee.server.IServer</value> - </property> - <property name=“service”> - <ref bean=“serverImplID”/> - </property> - <property name=“serviceName”> - <value>XXXX</value> - </property> - </bean> - 客户端
- 配置spring.xml 文件
- <!— spring提供专用于RMI远程服务代理工厂类 ⇒ - <bean id=“rmiProxyFactoryBeanID” class=“org.springframework.remoting.rmi.RmiProxyFactoryBean”> - <!— 协议名://远程提供服务的IP地址:提供服务的端口/提供服务的名称 ⇒ - <property name=“serviceUrl”> - <value>rmi://127.0.0.1:1099/XXXX</value> - </property> - <property name=“serviceInterface”> - <value>jee.client.IServer</value> - </property> - </bean> - 执行:
- 服务端加载 ApplicationContext类
- 客户端
- 加载 ApplicationContext类 ac
- ac.getBean方法中得到RmiProxyFactoryBean实际类型(可变类型)的实例,强转成服务端自定义的接口IServer的实现类(实现类由服务器决定)
- 执行IServer实现类中的方法int rax(int),实现了远程调用
- websocket
- handler
- extends TextWebSocketHandler
- @Override
- handleTextMessge() # 处理client.send()的数据
- @Override
- afterConnectionEstablished(WebSocketSession) # 连接事件
- @Override
- handleTransportError() # 出错事件
- @Override
- afterConnectionClosed() # 断开事件
- @Override
- supportsPartialMessages() # 并行处理
- config
- @EnableWebSocket
- implements WebSocketConfigurer
- @Override
- registerWebSocketHandlers()
- registry.addHandler(handler, “/ws”) # 路由handler
- client
- extends WebSocketClient
- constructor(uri)
- @Override
- onOpen()
- @Override
- onClose()
- @Override
- onError()
- @Override
- onMessage()
- service
- init()
- client = new Client(“ws://127.0.0.1:8001/ws”)
- client.connectBlocking()
- send()
- while(!client.getReadyState().equals(ReadyState.OPEN)){
- }
- client.send("")
- runner
- implements ApplicationRunner