diff --git a/code/IPersistence/pom.xml b/code/IPersistence/pom.xml deleted file mode 100644 index aad96d7ea57f65bb51142cbb92c881ae7ba7154f..0000000000000000000000000000000000000000 --- a/code/IPersistence/pom.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - 4.0.0 - - com.lagou - IPersistence - 1.0-SNAPSHOT - - - UTF-8 - UTF-8 - 1.8 - 1.8 - 1.8 - - - - - - mysql - mysql-connector-java - 8.0.19 - - - c3p0 - c3p0 - 0.9.1.2 - - - log4j - log4j - 1.2.12 - - - junit - junit - 4.10 - - - dom4j - dom4j - 1.6.1 - - - jaxen - jaxen - 1.1.6 - - - - - - - \ No newline at end of file diff --git a/code/IPersistence/src/main/java/com/lagou/config/BoundSql.java b/code/IPersistence/src/main/java/com/lagou/config/BoundSql.java deleted file mode 100644 index 1e428aabb00ba6d4f95ec5a3d0595f2b05bfe76b..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/config/BoundSql.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.lagou.config; - -import com.lagou.utils.ParameterMapping; - -import java.util.ArrayList; -import java.util.List; - -public class BoundSql { - - private String sqlText; //解析过后的sql - - private List parameterMappingList = new ArrayList<>(); - - public BoundSql(String sqlText, List parameterMappingList) { - this.sqlText = sqlText; - this.parameterMappingList = parameterMappingList; - } - - public String getSqlText() { - return sqlText; - } - - public void setSqlText(String sqlText) { - this.sqlText = sqlText; - } - - public List getParameterMappingList() { - return parameterMappingList; - } - - public void setParameterMappingList(List parameterMappingList) { - this.parameterMappingList = parameterMappingList; - } - - @Override - public String toString() { - return "BoundSql{" + - "sqlText='" + sqlText + '\'' + - ", parameterMappingList=" + parameterMappingList + - '}'; - } -} diff --git a/code/IPersistence/src/main/java/com/lagou/config/XMLConfigBuilder.java b/code/IPersistence/src/main/java/com/lagou/config/XMLConfigBuilder.java deleted file mode 100644 index ab9e2255b1363f82680741c2293445ab15ab528b..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/config/XMLConfigBuilder.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.lagou.config; - -import com.lagou.io.Resources; -import com.lagou.pojo.Configuration; -import com.mchange.v2.c3p0.ComboPooledDataSource; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; - -import java.beans.PropertyVetoException; -import java.io.InputStream; -import java.util.List; -import java.util.Properties; - -public class XMLConfigBuilder { - - private Configuration configuration; - - public XMLConfigBuilder() { - this.configuration = new Configuration(); - } - - /** - * 该方法就是使用dom4j对配置文件进行解析,封装Configuration - */ - public Configuration parseConfig(InputStream inputStream) throws DocumentException, PropertyVetoException { - - Document document = new SAXReader().read(inputStream); - // - Element rootElement = document.getRootElement(); - List list = rootElement.selectNodes("//property"); - Properties properties = new Properties(); - for (Element element : list) { - String name = element.attributeValue("name"); - String value = element.attributeValue("value"); - properties.setProperty(name,value); - } - - ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); - comboPooledDataSource.setDriverClass(properties.getProperty("driverClass")); - comboPooledDataSource.setJdbcUrl(properties.getProperty("jdbcUrl")); - comboPooledDataSource.setUser(properties.getProperty("username")); - comboPooledDataSource.setPassword(properties.getProperty("password")); - - configuration.setDataSource(comboPooledDataSource); - - //mapper.xml解析: 拿到路径--字节输入流---dom4j进行解析 - List mapperList = rootElement.selectNodes("//mapper"); - - for (Element element : mapperList) { - String mapperPath = element.attributeValue("resource"); - InputStream resourceAsSteam = Resources.getResourceAsSteam(mapperPath); - XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configuration); - xmlMapperBuilder.parse(resourceAsSteam); - - } - - - - - return configuration; - } - - -} diff --git a/code/IPersistence/src/main/java/com/lagou/config/XMLMapperBuilder.java b/code/IPersistence/src/main/java/com/lagou/config/XMLMapperBuilder.java deleted file mode 100644 index d69d0cebbda2314ca99a5dfd27e2f099ae7ac7d5..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/config/XMLMapperBuilder.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.lagou.config; - -import com.lagou.pojo.Configuration; -import com.lagou.pojo.MappedStatement; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; - -import java.io.InputStream; -import java.util.List; - -public class XMLMapperBuilder { - - private Configuration configuration; - - public XMLMapperBuilder(Configuration configuration) { - this.configuration =configuration; - } - - public void parse(InputStream inputStream) throws DocumentException { - - Document document = new SAXReader().read(inputStream); - Element rootElement = document.getRootElement(); - - String namespace = rootElement.attributeValue("namespace"); - - List list = rootElement.selectNodes("//select"); - addList(rootElement, list, "//insert"); - addList(rootElement, list, "//delete"); - addList(rootElement, list, "//update"); - - for (Element element : list) { - String id = element.attributeValue("id"); - String resultType = element.attributeValue("resultType"); - String paramterType = element.attributeValue("paramterType"); - String sqlText = element.getTextTrim(); - MappedStatement mappedStatement = new MappedStatement(); - mappedStatement.setId(id); - mappedStatement.setResultType(resultType); - mappedStatement.setParamterType(paramterType); - mappedStatement.setSql(sqlText); - String key = namespace+"."+id; - configuration.getMappedStatementMap().put(key,mappedStatement); - - } - - } - - private void addList(Element rootElement, List list, String xpathExpression) { - List insertList = rootElement.selectNodes(xpathExpression); - if (insertList !=null && insertList.size() >0){ - list.addAll(insertList); - } - } - - -} diff --git a/code/IPersistence/src/main/java/com/lagou/io/Resources.java b/code/IPersistence/src/main/java/com/lagou/io/Resources.java deleted file mode 100644 index 819cd296b62ca0c178f177b95fc34e03bc5a1365..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/io/Resources.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.lagou.io; - -import java.io.InputStream; - -public class Resources { - - // 根据配置文件的路径,将配置文件加载成字节输入流,存储在内存中 - public static InputStream getResourceAsSteam(String path){ - InputStream resourceAsStream = Resources.class.getClassLoader().getResourceAsStream(path); - return resourceAsStream; - - } - - - -} diff --git a/code/IPersistence/src/main/java/com/lagou/pojo/Configuration.java b/code/IPersistence/src/main/java/com/lagou/pojo/Configuration.java deleted file mode 100644 index 0543481bfae967f70e6d81149766939b50de92cd..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/pojo/Configuration.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.lagou.pojo; - -import javax.sql.DataSource; -import java.util.HashMap; -import java.util.Map; - -public class Configuration { - - private DataSource dataSource; - - /* - * key: statementid value:封装好的mappedStatement对象 - * */ - Map mappedStatementMap = new HashMap<>(); - - public DataSource getDataSource() { - return dataSource; - } - - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - } - - public Map getMappedStatementMap() { - return mappedStatementMap; - } - - public void setMappedStatementMap(Map mappedStatementMap) { - this.mappedStatementMap = mappedStatementMap; - } -} diff --git a/code/IPersistence/src/main/java/com/lagou/pojo/MappedStatement.java b/code/IPersistence/src/main/java/com/lagou/pojo/MappedStatement.java deleted file mode 100644 index 3c62aa9c7c2bb3d8d0f6cfd3a5e71aac72bd7d4e..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/pojo/MappedStatement.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.lagou.pojo; - -public class MappedStatement { - - //id标识 - private String id; - //返回值类型 - private String resultType; - //参数值类型 - private String paramterType; - //sql语句 - private String sql; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getResultType() { - return resultType; - } - - public void setResultType(String resultType) { - this.resultType = resultType; - } - - public String getParamterType() { - return paramterType; - } - - public void setParamterType(String paramterType) { - this.paramterType = paramterType; - } - - public String getSql() { - return sql; - } - - public void setSql(String sql) { - this.sql = sql; - } -} diff --git a/code/IPersistence/src/main/java/com/lagou/sqlSession/DefaultSqlSession.java b/code/IPersistence/src/main/java/com/lagou/sqlSession/DefaultSqlSession.java deleted file mode 100644 index 5e93082f01c63401c85f9fd646dedc06ef9b8021..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/sqlSession/DefaultSqlSession.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.lagou.sqlSession; - -import com.lagou.pojo.Configuration; -import com.lagou.pojo.MappedStatement; - -import java.lang.reflect.*; -import java.util.List; -import java.util.Locale; - -public class DefaultSqlSession implements SqlSession { - - private Configuration configuration; - - public DefaultSqlSession(Configuration configuration) { - this.configuration = configuration; - } - - @Override - public int update(String statementid, Object... params) throws Exception { - simpleExecutor simpleExecutor = new simpleExecutor(); - MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementid); - return simpleExecutor.update(configuration, mappedStatement, params); - } - - @Override - public List selectList(String statementid, Object... params) throws Exception { - - //将要去完成对simpleExecutor里的query方法的调用 - simpleExecutor simpleExecutor = new simpleExecutor(); - MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementid); - List list = simpleExecutor.query(configuration, mappedStatement, params); - - return (List) list; - } - - @Override - public T selectOne(String statementid, Object... params) throws Exception { - List objects = selectList(statementid, params); - if(objects.size()==1){ - return (T) objects.get(0); - }else { - throw new RuntimeException("查询结果为空或者返回结果过多"); - } - } - - @Override - public T getMapper(Class mapperClass) { - // 使用JDK动态代理来为Dao接口生成代理对象,并返回 - - Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() { - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - // 底层都还是去执行JDBC代码 //根据不同情况,来调用selctList或者selectOne - // 准备参数 1:statmentid :sql语句的唯一标识:namespace.id= 接口全限定名.方法名 - // 方法名:findAll - String methodName = method.getName(); - String className = method.getDeclaringClass().getName(); - - String statementId = className+"."+methodName; - - MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId); - if (mappedStatement == null){ - throw new RuntimeException("方法未定义!"); - } - String sql = mappedStatement.getSql(); - if (sql.toLowerCase(Locale.ROOT).startsWith( "select" )){ - // 准备参数2:params:args - // 获取被调用方法的返回值类型 - Type genericReturnType = method.getGenericReturnType(); - // 判断是否进行了 泛型类型参数化 - if(genericReturnType instanceof ParameterizedType){ - List objects = selectList(statementId, args); - return objects; - } - return selectOne(statementId,args); - } - else if (sql.toLowerCase(Locale.ROOT).startsWith( "insert" )){ - return update(statementId , args); - } - else if (sql.toLowerCase(Locale.ROOT).startsWith( "delete" )){ - return update(statementId , args); - } - else if (sql.toLowerCase(Locale.ROOT).startsWith( "update" )){ - return update(statementId , args); - } - return null; - } - }); - - return (T) proxyInstance; - } - - -} diff --git a/code/IPersistence/src/main/java/com/lagou/sqlSession/DefaultSqlSessionFactory.java b/code/IPersistence/src/main/java/com/lagou/sqlSession/DefaultSqlSessionFactory.java deleted file mode 100644 index b4b27aa947dd4653e35fb0e9a3af0302dd1c61fb..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/sqlSession/DefaultSqlSessionFactory.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.lagou.sqlSession; - -import com.lagou.pojo.Configuration; - -public class DefaultSqlSessionFactory implements SqlSessionFactory { - - private Configuration configuration; - - public DefaultSqlSessionFactory(Configuration configuration) { - this.configuration = configuration; - } - - - @Override - public SqlSession openSession() { - return new DefaultSqlSession(configuration); - } -} diff --git a/code/IPersistence/src/main/java/com/lagou/sqlSession/Executor.java b/code/IPersistence/src/main/java/com/lagou/sqlSession/Executor.java deleted file mode 100644 index 19547a77d9db22f7b79a68f20e791f7eab67e214..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/sqlSession/Executor.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.lagou.sqlSession; - -import com.lagou.pojo.Configuration; -import com.lagou.pojo.MappedStatement; - -import java.beans.IntrospectionException; -import java.lang.reflect.InvocationTargetException; -import java.sql.SQLException; -import java.util.List; - -public interface Executor { - - public List query(Configuration configuration,MappedStatement mappedStatement,Object... params) throws Exception; - - int update(Configuration configuration, MappedStatement mappedStatement, Object[] params) throws SQLException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, IntrospectionException, InvocationTargetException; -} diff --git a/code/IPersistence/src/main/java/com/lagou/sqlSession/SqlSession.java b/code/IPersistence/src/main/java/com/lagou/sqlSession/SqlSession.java deleted file mode 100644 index f7d9d5b1de7b2648921dd1021c95b76a4e019777..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/sqlSession/SqlSession.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.lagou.sqlSession; - -import java.util.List; - -public interface SqlSession { - - //查询所有 - public List selectList(String statementid,Object... params) throws Exception; - - //根据条件查询单个 - public T selectOne(String statementid,Object... params) throws Exception; - - public int update(String statementid,Object... params) throws Exception; - - //为Dao接口生成代理实现类 - public T getMapper(Class mapperClass); - - -} diff --git a/code/IPersistence/src/main/java/com/lagou/sqlSession/SqlSessionFactory.java b/code/IPersistence/src/main/java/com/lagou/sqlSession/SqlSessionFactory.java deleted file mode 100644 index df5bba287448fa7b1ae88ad81b2eb1ff5eb735c9..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/sqlSession/SqlSessionFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.lagou.sqlSession; - -public interface SqlSessionFactory { - - public SqlSession openSession(); - - -} diff --git a/code/IPersistence/src/main/java/com/lagou/sqlSession/SqlSessionFactoryBuilder.java b/code/IPersistence/src/main/java/com/lagou/sqlSession/SqlSessionFactoryBuilder.java deleted file mode 100644 index 93fc83be2fbf2d95b24e957d9d02ceb41d267a0f..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/sqlSession/SqlSessionFactoryBuilder.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lagou.sqlSession; - -import com.lagou.config.XMLConfigBuilder; -import com.lagou.pojo.Configuration; -import org.dom4j.DocumentException; - -import java.beans.PropertyVetoException; -import java.io.InputStream; - -public class SqlSessionFactoryBuilder { - - public SqlSessionFactory build(InputStream in) throws DocumentException, PropertyVetoException { - // 第一:使用dom4j解析配置文件,将解析出来的内容封装到Configuration中 - XMLConfigBuilder xmlConfigBuilder = new XMLConfigBuilder(); - Configuration configuration = xmlConfigBuilder.parseConfig(in); - - - // 第二:创建sqlSessionFactory对象:工厂类:生产sqlSession:会话对象 - DefaultSqlSessionFactory defaultSqlSessionFactory = new DefaultSqlSessionFactory(configuration); - - return defaultSqlSessionFactory; - } - - - - -} diff --git a/code/IPersistence/src/main/java/com/lagou/sqlSession/simpleExecutor.java b/code/IPersistence/src/main/java/com/lagou/sqlSession/simpleExecutor.java deleted file mode 100644 index 5be4c967fdfb30309886c4085d3056ab1b41e1e9..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/sqlSession/simpleExecutor.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.lagou.sqlSession; - - -import com.lagou.config.BoundSql; -import com.lagou.pojo.Configuration; -import com.lagou.pojo.MappedStatement; -import com.lagou.utils.GenericTokenParser; -import com.lagou.utils.ParameterMapping; -import com.lagou.utils.ParameterMappingTokenHandler; - -import java.beans.IntrospectionException; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.sql.*; -import java.util.ArrayList; -import java.util.List; - -public class simpleExecutor implements Executor { - - @Override - public int update(Configuration configuration, MappedStatement mappedStatement, Object[] params) throws SQLException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, IntrospectionException, InvocationTargetException { - // 1. 注册驱动,获取连接 - Connection connection = configuration.getDataSource().getConnection(); - - // 2. 获取sql语句 : select * from user where id = #{id} and username = #{username} - //转换sql语句: select * from user where id = ? and username = ? ,转换的过程中,还需要对#{}里面的值进行解析存储 - String sql = mappedStatement.getSql(); - BoundSql boundSql = getBoundSql(sql); - - // 3.获取预处理对象:preparedStatement - PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText()); - - // 4. 设置参数 - //获取到了参数的全路径 - handleParam(mappedStatement, boundSql, preparedStatement, params[0]); - - // 5. 执行sql - int res = preparedStatement.executeUpdate(); - return res; - - } - - @Override //user - public List query(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception { - // 1. 注册驱动,获取连接 - Connection connection = configuration.getDataSource().getConnection(); - - // 2. 获取sql语句 : select * from user where id = #{id} and username = #{username} - //转换sql语句: select * from user where id = ? and username = ? ,转换的过程中,还需要对#{}里面的值进行解析存储 - String sql = mappedStatement.getSql(); - BoundSql boundSql = getBoundSql(sql); - - // 3.获取预处理对象:preparedStatement - PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText()); - - // 4. 设置参数 - Object param = null; - if(params !=null && params.length > 0){ - param = params[0]; - } - handleParam(mappedStatement, boundSql, preparedStatement, param); - - - // 5. 执行sql - ResultSet resultSet = preparedStatement.executeQuery(); - String resultType = mappedStatement.getResultType(); - Class resultTypeClass = getClassType(resultType); - - ArrayList objects = new ArrayList<>(); - - // 6. 封装返回结果集 - while (resultSet.next()){ - Object o =resultTypeClass.newInstance(); - //元数据 - ResultSetMetaData metaData = resultSet.getMetaData(); - for (int i = 1; i <= metaData.getColumnCount(); i++) { - - // 字段名 - String columnName = metaData.getColumnName(i); - // 字段的值 - Object value = resultSet.getObject(columnName); - - //使用反射或者内省,根据数据库表和实体的对应关系,完成封装 - PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName, resultTypeClass); - Method writeMethod = propertyDescriptor.getWriteMethod(); - writeMethod.invoke(o,value); - - - } - objects.add(o); - - } - return (List) objects; - - } - - private void handleParam(MappedStatement mappedStatement, BoundSql boundSql, PreparedStatement preparedStatement, Object param) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, SQLException { - //获取到了参数的全路径 - String paramterType = mappedStatement.getParamterType(); - Class paramtertypeClass = getClassType(paramterType); - - List parameterMappingList = boundSql.getParameterMappingList(); - - System.out.println( boundSql ); - System.out.print("参数: "); - for (int i = 0; i < parameterMappingList.size(); i++) { - ParameterMapping parameterMapping = parameterMappingList.get(i); - String content = parameterMapping.getContent(); - - //反射 - Field declaredField = paramtertypeClass.getDeclaredField(content); - //暴力访问 - declaredField.setAccessible(true); - Object o = declaredField.get(param); - - preparedStatement.setObject(i+1,o); - System.out.print(o + " "); - } - System.out.println(); - } - - private Class getClassType(String paramterType) throws ClassNotFoundException { - if(paramterType!=null){ - Class aClass = Class.forName(paramterType); - return aClass; - } - return null; - - } - - - /** - * 完成对#{}的解析工作:1.将#{}使用?进行代替,2.解析出#{}里面的值进行存储 - * @param sql - * @return - */ - private BoundSql getBoundSql(String sql) { - //标记处理类:配置标记解析器来完成对占位符的解析处理工作 - ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler(); - GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}", parameterMappingTokenHandler); - //解析出来的sql - String parseSql = genericTokenParser.parse(sql); - //#{}里面解析出来的参数名称 - List parameterMappings = parameterMappingTokenHandler.getParameterMappings(); - - BoundSql boundSql = new BoundSql(parseSql,parameterMappings); - return boundSql; - - } - - -} diff --git a/code/IPersistence/src/main/java/com/lagou/utils/GenericTokenParser.java b/code/IPersistence/src/main/java/com/lagou/utils/GenericTokenParser.java deleted file mode 100644 index d92cd5e42b3615574873c60a10c4386f49613e35..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/utils/GenericTokenParser.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright 2009-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.lagou.utils; - -/** - * @author Clinton Begin - */ -public class GenericTokenParser { - - private final String openToken; //开始标记 - private final String closeToken; //结束标记 - private final TokenHandler handler; //标记处理器 - - public GenericTokenParser(String openToken, String closeToken, TokenHandler handler) { - this.openToken = openToken; - this.closeToken = closeToken; - this.handler = handler; - } - - /** - * 解析${}和#{} - * @param text - * @return - * 该方法主要实现了配置文件、脚本等片段中占位符的解析、处理工作,并返回最终需要的数据。 - * 其中,解析工作由该方法完成,处理工作是由处理器handler的handleToken()方法来实现 - */ - public String parse(String text) { - // 验证参数问题,如果是null,就返回空字符串。 - if (text == null || text.isEmpty()) { - return ""; - } - - // 下面继续验证是否包含开始标签,如果不包含,默认不是占位符,直接原样返回即可,否则继续执行。 - int start = text.indexOf(openToken, 0); - if (start == -1) { - return text; - } - - // 把text转成字符数组src,并且定义默认偏移量offset=0、存储最终需要返回字符串的变量builder, - // text变量中占位符对应的变量名expression。判断start是否大于-1(即text中是否存在openToken),如果存在就执行下面代码 - char[] src = text.toCharArray(); - int offset = 0; - final StringBuilder builder = new StringBuilder(); - StringBuilder expression = null; - while (start > -1) { - // 判断如果开始标记前如果有转义字符,就不作为openToken进行处理,否则继续处理 - if (start > 0 && src[start - 1] == '\\') { - builder.append(src, offset, start - offset - 1).append(openToken); - offset = start + openToken.length(); - } else { - //重置expression变量,避免空指针或者老数据干扰。 - if (expression == null) { - expression = new StringBuilder(); - } else { - expression.setLength(0); - } - builder.append(src, offset, start - offset); - offset = start + openToken.length(); - int end = text.indexOf(closeToken, offset); - while (end > -1) {////存在结束标记时 - if (end > offset && src[end - 1] == '\\') {//如果结束标记前面有转义字符时 - // this close token is escaped. remove the backslash and continue. - expression.append(src, offset, end - offset - 1).append(closeToken); - offset = end + closeToken.length(); - end = text.indexOf(closeToken, offset); - } else {//不存在转义字符,即需要作为参数进行处理 - expression.append(src, offset, end - offset); - offset = end + closeToken.length(); - break; - } - } - if (end == -1) { - // close token was not found. - builder.append(src, start, src.length - start); - offset = src.length; - } else { - //首先根据参数的key(即expression)进行参数处理,返回?作为占位符 - builder.append(handler.handleToken(expression.toString())); - offset = end + closeToken.length(); - } - } - start = text.indexOf(openToken, offset); - } - if (offset < src.length) { - builder.append(src, offset, src.length - offset); - } - return builder.toString(); - } -} diff --git a/code/IPersistence/src/main/java/com/lagou/utils/ParameterMapping.java b/code/IPersistence/src/main/java/com/lagou/utils/ParameterMapping.java deleted file mode 100644 index 9754ce74c0e685cde7790fae9d142ad3b647f4ce..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/utils/ParameterMapping.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.lagou.utils; - -public class ParameterMapping { - - private String content; - - public ParameterMapping(String content) { - this.content = content; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - @Override - public String toString() { - return "ParameterMapping{" + - "content='" + content + '\'' + - '}'; - } -} diff --git a/code/IPersistence/src/main/java/com/lagou/utils/ParameterMappingTokenHandler.java b/code/IPersistence/src/main/java/com/lagou/utils/ParameterMappingTokenHandler.java deleted file mode 100644 index 205cdcc8506f4585b64f9b9ed5707087ff7505bf..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/utils/ParameterMappingTokenHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.lagou.utils; - -import java.util.ArrayList; -import java.util.List; - - - - -public class ParameterMappingTokenHandler implements TokenHandler { - private List parameterMappings = new ArrayList(); - - // context是参数名称 #{id} #{username} - - public String handleToken(String content) { - parameterMappings.add(buildParameterMapping(content)); - return "?"; - } - - private ParameterMapping buildParameterMapping(String content) { - ParameterMapping parameterMapping = new ParameterMapping(content); - return parameterMapping; - } - - public List getParameterMappings() { - return parameterMappings; - } - - public void setParameterMappings(List parameterMappings) { - this.parameterMappings = parameterMappings; - } - -} diff --git a/code/IPersistence/src/main/java/com/lagou/utils/TokenHandler.java b/code/IPersistence/src/main/java/com/lagou/utils/TokenHandler.java deleted file mode 100644 index 566d90bbc46534f1804eeb3d01d0797aa3f4cc63..0000000000000000000000000000000000000000 --- a/code/IPersistence/src/main/java/com/lagou/utils/TokenHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright 2009-2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.lagou.utils; - -/** - * @author Clinton Begin - */ -public interface TokenHandler { - String handleToken(String content); -} - diff --git a/code/IPersistence_test/pom.xml b/code/IPersistence_test/pom.xml deleted file mode 100644 index a91d26318fe72c6afa9a5afaf82d407257416638..0000000000000000000000000000000000000000 --- a/code/IPersistence_test/pom.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - 4.0.0 - - com.lagou - IPersistence_test - 1.0-SNAPSHOT - - - UTF-8 - UTF-8 - 1.8 - 1.8 - 1.8 - - - - - - com.lagou - IPersistence - 1.0-SNAPSHOT - - - - - - \ No newline at end of file diff --git a/code/IPersistence_test/src/main/java/com/lagou/dao/IUserDao.java b/code/IPersistence_test/src/main/java/com/lagou/dao/IUserDao.java deleted file mode 100644 index 9e09de486a741da1c29000e9803f6272500c1d2d..0000000000000000000000000000000000000000 --- a/code/IPersistence_test/src/main/java/com/lagou/dao/IUserDao.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.lagou.dao; - -import com.lagou.pojo.User; - -import java.util.List; - -public interface IUserDao { - - //查询所有用户 - public List findAll() throws Exception; - - - //根据条件进行用户查询 - public User findByCondition(User user) throws Exception; - - public int insertOne(User user) throws Exception; - - public int deleteById(User user) throws Exception; - - public int updateById(User user) throws Exception; - -} diff --git a/code/IPersistence_test/src/main/java/com/lagou/pojo/User.java b/code/IPersistence_test/src/main/java/com/lagou/pojo/User.java deleted file mode 100644 index ea5e98cbd85e4b435ce3775e8154a41fc6bca608..0000000000000000000000000000000000000000 --- a/code/IPersistence_test/src/main/java/com/lagou/pojo/User.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.lagou.pojo; - -public class User { - - private Integer id; - private String username; - private String password; - private String birthday; - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getBirthday() { - return birthday; - } - - public void setBirthday(String birthday) { - this.birthday = birthday; - } - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - @Override - public String toString() { - return "User{" + - "id=" + id + - ", username='" + username + '\'' + - ", password='" + password + '\'' + - ", birthday='" + birthday + '\'' + - '}'; - } -} diff --git a/code/IPersistence_test/src/main/java/com/lagou/test/IPersistenceTest.java b/code/IPersistence_test/src/main/java/com/lagou/test/IPersistenceTest.java deleted file mode 100644 index 6b0c7e3942086d02ebdca3694d0b017d9c42674e..0000000000000000000000000000000000000000 --- a/code/IPersistence_test/src/main/java/com/lagou/test/IPersistenceTest.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.lagou.test; - -import com.lagou.dao.IUserDao; -import com.lagou.io.Resources; -import com.lagou.pojo.User; -import com.lagou.sqlSession.SqlSession; -import com.lagou.sqlSession.SqlSessionFactory; -import com.lagou.sqlSession.SqlSessionFactoryBuilder; -import org.dom4j.DocumentException; -import org.junit.Before; -import org.junit.Test; - -import java.beans.PropertyVetoException; -import java.io.InputStream; -import java.util.List; - -public class IPersistenceTest { - - private IUserDao userDao; - - @Before - public void before() throws PropertyVetoException, DocumentException { - InputStream resourceAsSteam = Resources.getResourceAsSteam("sqlMapConfig.xml"); - SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsSteam); - SqlSession sqlSession = sqlSessionFactory.openSession(); - userDao = sqlSession.getMapper(IUserDao.class); - } - - @Test - public void testInsert() throws Exception { - User user = new User(); - user.setUsername("test"); - int num = userDao.insertOne(user); - System.out.println( "insertOne num is " + num ); - } - - @Test - public void testUpdate() throws Exception { - User user = new User(); - user.setId(4); - user.setUsername("testU"); - int num = userDao.updateById(user); - System.out.println( "updateById num is " + num ); - } - - @Test - public void testDelete() throws Exception { - User user = new User(); - user.setId(4); - int num = userDao.deleteById(user); - System.out.println( "updateById num is " + num ); - } - - @Test - public void tesFindAll() throws Exception { - //调用 - User user = new User(); - user.setId(1); - user.setUsername("张三"); - /* User user2 = sqlSession.selectOne("user.selectOne", user); - System.out.println(user2);*/ - - /* List users = sqlSession.selectList("user.selectList"); - for (User user1 : users) { - System.out.println(user1); - }*/ - - List all = userDao.findAll(); - for (User user1 : all) { - System.out.println(user1); - } - } - - @Test - public void tesFindByCondition() throws Exception { - //调用 - User user = new User(); - user.setId(1); - user.setUsername("lisi"); - - User res = userDao.findByCondition(user); - System.out.println(res); - } -} diff --git a/code/IPersistence_test/src/main/resources/ProductMapper.xml b/code/IPersistence_test/src/main/resources/ProductMapper.xml deleted file mode 100644 index 400d3ecbbc7d05bb0cdb18ab2c11a2318102276a..0000000000000000000000000000000000000000 --- a/code/IPersistence_test/src/main/resources/ProductMapper.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/code/IPersistence_test/src/main/resources/UserMapper.xml b/code/IPersistence_test/src/main/resources/UserMapper.xml deleted file mode 100644 index f83e771d40a233abe7965f6a359fef80fa4238ff..0000000000000000000000000000000000000000 --- a/code/IPersistence_test/src/main/resources/UserMapper.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - INSERT INTO `user`( `username`, `password`, `birthday`) - VALUES ( #{username}, #{password}, #{birthday}); - - - DELETE FROM `user` WHERE `id` = #{id} - - - UPDATE `user` SET `username` = #{username} WHERE `id` = #{id} - - \ No newline at end of file diff --git a/code/IPersistence_test/src/main/resources/sqlMapConfig.xml b/code/IPersistence_test/src/main/resources/sqlMapConfig.xml deleted file mode 100644 index 634af73ad210bd876fd9a2c9b571dfea0d221521..0000000000000000000000000000000000000000 --- a/code/IPersistence_test/src/main/resources/sqlMapConfig.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/code/lagou-transfer/pom.xml b/code/lagou-transfer/pom.xml new file mode 100755 index 0000000000000000000000000000000000000000..3c3af84d249e10da98cb5e264bbcf01af835fb8d --- /dev/null +++ b/code/lagou-transfer/pom.xml @@ -0,0 +1,114 @@ + + + + 4.0.0 + + com.lagou.edu + lagou-transfer + 1.0-SNAPSHOT + war + + lagou-transfer Maven Webapp + + http://www.example.com + + + UTF-8 + 8 + 8 + + + + + + + + org.reflections + reflections + 0.9.12 + + + + + junit + junit + 4.12 + + + + + mysql + mysql-connector-java + 8.0.19 + + + + com.alibaba + druid + 1.1.21 + + + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + + com.fasterxml.jackson.core + jackson-databind + 2.9.6 + + + + + dom4j + dom4j + 1.6.1 + + + + jaxen + jaxen + 1.1.6 + + + + cglib + cglib + 2.1_2 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.2 + + 8 + 8 + UTF-8 + + + + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + 8080 + / + + + + + diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/annotation/Autowired.java b/code/lagou-transfer/src/main/java/com/lagou/edu/annotation/Autowired.java new file mode 100644 index 0000000000000000000000000000000000000000..aabf012082b1261f7120672b84491cd02f816569 --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/annotation/Autowired.java @@ -0,0 +1,11 @@ +package com.lagou.edu.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Autowired { +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/annotation/Repository.java b/code/lagou-transfer/src/main/java/com/lagou/edu/annotation/Repository.java new file mode 100644 index 0000000000000000000000000000000000000000..01445a4fe3849055567904ad7eebf57510499ab2 --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/annotation/Repository.java @@ -0,0 +1,12 @@ +package com.lagou.edu.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Repository { + String value() default ""; +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/annotation/Service.java b/code/lagou-transfer/src/main/java/com/lagou/edu/annotation/Service.java new file mode 100644 index 0000000000000000000000000000000000000000..02303b51665ca3e0d40ab854c8b354a1ba0e9d8a --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/annotation/Service.java @@ -0,0 +1,12 @@ +package com.lagou.edu.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Service { + String value() default ""; +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/annotation/Transactional.java b/code/lagou-transfer/src/main/java/com/lagou/edu/annotation/Transactional.java new file mode 100644 index 0000000000000000000000000000000000000000..5c529119ec5f8af06d90c74393cb5319e31c84d1 --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/annotation/Transactional.java @@ -0,0 +1,11 @@ +package com.lagou.edu.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Transactional { +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/dao/AccountDao.java b/code/lagou-transfer/src/main/java/com/lagou/edu/dao/AccountDao.java new file mode 100755 index 0000000000000000000000000000000000000000..462ad14477d321c9c0c6512d0dfcce25b7f8a9b4 --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/dao/AccountDao.java @@ -0,0 +1,13 @@ +package com.lagou.edu.dao; + +import com.lagou.edu.pojo.Account; + +/** + * @author 应癫 + */ +public interface AccountDao { + + Account queryAccountByCardNo(String cardNo) throws Exception; + + int updateAccountByCardNo(Account account) throws Exception; +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/dao/impl/JdbcAccountDaoImpl.java b/code/lagou-transfer/src/main/java/com/lagou/edu/dao/impl/JdbcAccountDaoImpl.java new file mode 100755 index 0000000000000000000000000000000000000000..5cd5f91c1a76d38028ae0dceb5ae0b6af84291ca --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/dao/impl/JdbcAccountDaoImpl.java @@ -0,0 +1,77 @@ +package com.lagou.edu.dao.impl; + +import com.lagou.edu.annotation.Autowired; +import com.lagou.edu.annotation.Repository; +import com.lagou.edu.pojo.Account; +import com.lagou.edu.dao.AccountDao; +import com.lagou.edu.utils.ConnectionUtils; +import com.lagou.edu.utils.DruidUtils; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + +/** + * @author 应癫 + */ +@Repository(value = "accountDao") +public class JdbcAccountDaoImpl implements AccountDao { + + @Autowired + private ConnectionUtils connectionUtils; + + public void setConnectionUtils(ConnectionUtils connectionUtils) { + this.connectionUtils = connectionUtils; + } + + + public void init() { + System.out.println("初始化方法....."); + } + + public void destory() { + System.out.println("销毁方法......"); + } + + @Override + public Account queryAccountByCardNo(String cardNo) throws Exception { + //从连接池获取连接 + // Connection con = DruidUtils.getInstance().getConnection(); + Connection con = connectionUtils.getCurrentThreadConn(); + String sql = "select * from account where cardNo=?"; + PreparedStatement preparedStatement = con.prepareStatement(sql); + preparedStatement.setString(1,cardNo); + ResultSet resultSet = preparedStatement.executeQuery(); + + Account account = new Account(); + while(resultSet.next()) { + account.setCardNo(resultSet.getString("cardNo")); + account.setName(resultSet.getString("name")); + account.setMoney(resultSet.getInt("money")); + } + + resultSet.close(); + preparedStatement.close(); + //con.close(); + + return account; + } + + @Override + public int updateAccountByCardNo(Account account) throws Exception { + + // 从连接池获取连接 + // 改造为:从当前线程当中获取绑定的connection连接 + //Connection con = DruidUtils.getInstance().getConnection(); + Connection con = connectionUtils.getCurrentThreadConn(); + String sql = "update account set money=? where cardNo=?"; + PreparedStatement preparedStatement = con.prepareStatement(sql); + preparedStatement.setInt(1,account.getMoney()); + preparedStatement.setString(2,account.getCardNo()); + int i = preparedStatement.executeUpdate(); + + preparedStatement.close(); + //con.close(); + return i; + } +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/factory/AnnotationBeanFactory.java b/code/lagou-transfer/src/main/java/com/lagou/edu/factory/AnnotationBeanFactory.java new file mode 100755 index 0000000000000000000000000000000000000000..d04d07c138bf4bb06d35bf00b06d9871034645bf --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/factory/AnnotationBeanFactory.java @@ -0,0 +1,135 @@ +package com.lagou.edu.factory; + +import com.alibaba.druid.util.StringUtils; +import com.lagou.edu.annotation.Autowired; +import com.lagou.edu.annotation.Repository; +import com.lagou.edu.annotation.Service; +import com.lagou.edu.annotation.Transactional; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import org.reflections.Reflections; + +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.*; + +/** + * + * 工厂类,生产对象(使用反射技术) 注解方式 + */ +public class AnnotationBeanFactory { + + // IOC容器 + private static Map map = new HashMap<>(); + + // 业务逻辑类 所在包 + private static final String reposityPackage = "com.lagou.edu"; + + /** + * 任务一: + * 扫描业务逻辑所在包的 @Repository 和 @Service注解标识的类,创建其实例 并 放入map集合; + * 扫描map集合中实例字段,有@Autowired修饰则进行依赖注入,若有@Transactional修饰则注入其代理类; + */ + static { + // 扫描业务包 reposityPackage 下所有@Repository 和 @Service注解标识的类 + Reflections reflections = new Reflections(reposityPackage); + Set> repositySet = new HashSet<>(); + repositySet.addAll( reflections.getTypesAnnotatedWith(Repository.class) ); + repositySet.addAll( reflections.getTypesAnnotatedWith(Service.class) ); + + // 创建单例对象放入容器(id为 注解的value 或者 类名小写首字母) + for (Class clazz : repositySet){ + try { + // 实例创建 + Object bean = clazz.newInstance(); + + // id确定 + Repository reposityAnnotation = (Repository) clazz.getAnnotation(Repository.class); + Service serviceAnnotation = (Service) clazz.getAnnotation(Service.class); + String clazzName = clazz.getName(); + String id = getBeanId(reposityAnnotation ,serviceAnnotation , clazzName); + + map.put(id , bean); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + // 依赖注入 + for (Map.Entry entry : map.entrySet()){ + String key = entry.getKey(); + Object value = entry.getValue(); + Class clazz = value.getClass(); + Field[] declaredFields = clazz.getDeclaredFields(); + for (Field f : declaredFields){ + if(f.isAnnotationPresent(Autowired.class)){ + // 获取容器中 字段名对应的对象 + String id = f.getName(); + Object o = map.get(id); + + f.setAccessible( true ); + try { + f.set(value , o); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + + // 代理对象替换 + if (clazz.isAnnotationPresent(Transactional.class)){ + ProxyFactory proxyFactory = (ProxyFactory)map.get("proxyFactory"); + Class[] interfaces = clazz.getInterfaces(); + if (interfaces != null && interfaces.length > 0){ + value = proxyFactory.getJdkProxy(value); + } else { + value = proxyFactory.getCglibProxy(value); + } + } + map.put(key , value); + } + } + + /** + * 优先取注解上的value值,若为空,则默认为 类名的首字母小写的字符串 + */ + private static String getBeanId(Repository reposityAnnotation, Service serviceAnnotation, String clazzName) { + if (reposityAnnotation != null && !StringUtils.isEmpty( reposityAnnotation.value() )){ + return reposityAnnotation.value(); + } + + if (serviceAnnotation != null && !StringUtils.isEmpty( serviceAnnotation.value() )){ + return serviceAnnotation.value(); + } + + int i = clazzName.lastIndexOf("."); + String value = clazzName.substring(i + 1, clazzName.length()); + value= toFirstOneLowerCase( value ); + return value; + } + + // 字符串首字母小写 + public static String toFirstOneLowerCase(String s){ + if(Character.isLowerCase( s.charAt( 0 ) )){ + return s; + } + + return new StringBuilder() + .append(Character.toLowerCase( s.charAt( 0 ) )) + .append(s.substring(1 , s.length())) + .toString(); + } + + // 任务二:对外提供获取实例对象的接口(根据id获取) + public static Object getBean(String id) { + return map.get(id); + } + +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/factory/BeanFactory.java b/code/lagou-transfer/src/main/java/com/lagou/edu/factory/BeanFactory.java new file mode 100755 index 0000000000000000000000000000000000000000..edb221cd48d4a4bccbfdd5c31d268b126a199354 --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/factory/BeanFactory.java @@ -0,0 +1,104 @@ +package com.lagou.edu.factory; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; + +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author 应癫 + * + * 工厂类,生产对象(使用反射技术) + */ +public class BeanFactory { + + /** + * 任务一:读取解析xml,通过反射技术实例化对象并且存储待用(map集合) + * 任务二:对外提供获取实例对象的接口(根据id获取) + */ + + private static Map map = new HashMap<>(); // 存储对象 + + + static { + // 任务一:读取解析xml,通过反射技术实例化对象并且存储待用(map集合) + // 加载xml + InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml"); + // 解析xml + SAXReader saxReader = new SAXReader(); + try { + Document document = saxReader.read(resourceAsStream); + Element rootElement = document.getRootElement(); + List beanList = rootElement.selectNodes("//bean"); + for (int i = 0; i < beanList.size(); i++) { + Element element = beanList.get(i); + // 处理每个bean元素,获取到该元素的id 和 class 属性 + String id = element.attributeValue("id"); // accountDao + String clazz = element.attributeValue("class"); // com.lagou.edu.dao.impl.JdbcAccountDaoImpl + // 通过反射技术实例化对象 + Class aClass = Class.forName(clazz); + Object o = aClass.newInstance(); // 实例化之后的对象 + + // 存储到map中待用 + map.put(id,o); + + } + + // 实例化完成之后维护对象的依赖关系,检查哪些对象需要传值进入,根据它的配置,我们传入相应的值 + // 有property子元素的bean就有传值需求 + List propertyList = rootElement.selectNodes("//property"); + // 解析property,获取父元素 + for (int i = 0; i < propertyList.size(); i++) { + Element element = propertyList.get(i); // + String name = element.attributeValue("name"); + String ref = element.attributeValue("ref"); + + // 找到当前需要被处理依赖关系的bean + Element parent = element.getParent(); + + // 调用父元素对象的反射功能 + String parentId = parent.attributeValue("id"); + Object parentObject = map.get(parentId); + // 遍历父对象中的所有方法,找到"set" + name + Method[] methods = parentObject.getClass().getMethods(); + for (int j = 0; j < methods.length; j++) { + Method method = methods[j]; + if(method.getName().equalsIgnoreCase("set" + name)) { // 该方法就是 setAccountDao(AccountDao accountDao) + method.invoke(parentObject,map.get(ref)); + } + } + + // 把处理之后的parentObject重新放到map中 + map.put(parentId,parentObject); + + } + + + } catch (DocumentException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + + } + + + // 任务二:对外提供获取实例对象的接口(根据id获取) + public static Object getBean(String id) { + return map.get(id); + } + +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/factory/ProxyFactory.java b/code/lagou-transfer/src/main/java/com/lagou/edu/factory/ProxyFactory.java new file mode 100755 index 0000000000000000000000000000000000000000..b34e8282bacce459f5819b0ba16ed82f1dabd5a6 --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/factory/ProxyFactory.java @@ -0,0 +1,115 @@ +package com.lagou.edu.factory; + +import com.lagou.edu.annotation.Autowired; +import com.lagou.edu.annotation.Repository; +import com.lagou.edu.pojo.Account; +import com.lagou.edu.utils.TransactionManager; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +/** + * @author 应癫 + * + * + * 代理对象工厂:生成代理对象的 + */ +@Repository +public class ProxyFactory { + + @Autowired + private TransactionManager transactionManager; + + public void setTransactionManager(TransactionManager transactionManager) { + this.transactionManager = transactionManager; + } + + /*private ProxyFactory(){ + + } + + private static ProxyFactory proxyFactory = new ProxyFactory(); + + public static ProxyFactory getInstance() { + return proxyFactory; + }*/ + + + + /** + * Jdk动态代理 + * @param obj 委托对象 + * @return 代理对象 + */ + public Object getJdkProxy(Object obj) { + + // 获取代理对象 + return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), + new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + Object result = null; + + try{ + // 开启事务(关闭事务的自动提交) + transactionManager.beginTransaction(); + + result = method.invoke(obj,args); + + // 提交事务 + + transactionManager.commit(); + }catch (Exception e) { + e.printStackTrace(); + // 回滚事务 + transactionManager.rollback(); + + // 抛出异常便于上层servlet捕获 + throw e; + + } + + return result; + } + }); + + } + + + /** + * 使用cglib动态代理生成代理对象 + * @param obj 委托对象 + * @return + */ + public Object getCglibProxy(Object obj) { + return Enhancer.create(obj.getClass(), new MethodInterceptor() { + @Override + public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { + Object result = null; + try{ + // 开启事务(关闭事务的自动提交) + transactionManager.beginTransaction(); + + result = method.invoke(obj,objects); + + // 提交事务 + + transactionManager.commit(); + }catch (Exception e) { + e.printStackTrace(); + // 回滚事务 + transactionManager.rollback(); + + // 抛出异常便于上层servlet捕获 + throw e; + + } + return result; + } + }); + } +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/pojo/Account.java b/code/lagou-transfer/src/main/java/com/lagou/edu/pojo/Account.java new file mode 100755 index 0000000000000000000000000000000000000000..50125a01bc08bef869a4cc5e251958137e70a080 --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/pojo/Account.java @@ -0,0 +1,40 @@ +package com.lagou.edu.pojo; + +/** + * @author 应癫 + */ +public class Account { + + private String cardNo; + private String name; + private int money; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getMoney() { + return money; + } + + public void setMoney(int money) { + this.money = money; + } + + public String getCardNo() { return cardNo; } + + public void setCardNo(String cardNo) { this.cardNo = cardNo;} + + @Override + public String toString() { + return "Account{" + + "cardNo='" + cardNo + '\'' + + ", name='" + name + '\'' + + ", money=" + money + + '}'; + } +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/pojo/Result.java b/code/lagou-transfer/src/main/java/com/lagou/edu/pojo/Result.java new file mode 100755 index 0000000000000000000000000000000000000000..3e3961da2c623b4c8d29cfd5698e23f097c7ea8a --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/pojo/Result.java @@ -0,0 +1,34 @@ +package com.lagou.edu.pojo; + +/** + * @author 应癫 + */ +public class Result { + + private String status; + private String message; + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return "Result{" + + "status='" + status + '\'' + + ", message='" + message + '\'' + + '}'; + } +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/service/TransferService.java b/code/lagou-transfer/src/main/java/com/lagou/edu/service/TransferService.java new file mode 100755 index 0000000000000000000000000000000000000000..fc75bbf8621ad3997e2c0010546688974603837e --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/service/TransferService.java @@ -0,0 +1,9 @@ +package com.lagou.edu.service; + +/** + * @author 应癫 + */ +public interface TransferService { + + void transfer(String fromCardNo,String toCardNo,int money) throws Exception; +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/service/impl/TransferServiceImpl.java b/code/lagou-transfer/src/main/java/com/lagou/edu/service/impl/TransferServiceImpl.java new file mode 100755 index 0000000000000000000000000000000000000000..e670a3ced6161868e64479c06b9b9666395fefa9 --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/service/impl/TransferServiceImpl.java @@ -0,0 +1,67 @@ +package com.lagou.edu.service.impl; + +import com.lagou.edu.annotation.Autowired; +import com.lagou.edu.annotation.Service; +import com.lagou.edu.dao.AccountDao; +import com.lagou.edu.pojo.Account; +import com.lagou.edu.service.TransferService; +import com.lagou.edu.utils.ConnectionUtils; +import com.lagou.edu.utils.TransactionManager; + +/** + * @author 应癫 + */ +@Service(value = "transferService") +public class TransferServiceImpl implements TransferService { + + //private AccountDao accountDao = new JdbcAccountDaoImpl(); + + // private AccountDao accountDao = (AccountDao) BeanFactory.getBean("accountDao"); + + // 最佳状态 + @Autowired + private AccountDao accountDao; + + // 构造函数传值/set方法传值 + + public void setAccountDao(AccountDao accountDao) { + this.accountDao = accountDao; + } + + + + @Override + public void transfer(String fromCardNo, String toCardNo, int money) throws Exception { + + /*try{ + // 开启事务(关闭事务的自动提交) + TransactionManager.getInstance().beginTransaction();*/ + + Account from = accountDao.queryAccountByCardNo(fromCardNo); + Account to = accountDao.queryAccountByCardNo(toCardNo); + + from.setMoney(from.getMoney()-money); + to.setMoney(to.getMoney()+money); + + accountDao.updateAccountByCardNo(to); + int c = 1/0; + accountDao.updateAccountByCardNo(from); + + /* // 提交事务 + + TransactionManager.getInstance().commit(); + }catch (Exception e) { + e.printStackTrace(); + // 回滚事务 + TransactionManager.getInstance().rollback(); + + // 抛出异常便于上层servlet捕获 + throw e; + + }*/ + + + + + } +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/servlet/TransferServlet.java b/code/lagou-transfer/src/main/java/com/lagou/edu/servlet/TransferServlet.java new file mode 100755 index 0000000000000000000000000000000000000000..d8d45d6a96b2265933bb1f018f256dc268c50953 --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/servlet/TransferServlet.java @@ -0,0 +1,65 @@ +package com.lagou.edu.servlet; + +import com.lagou.edu.factory.AnnotationBeanFactory; +import com.lagou.edu.factory.ProxyFactory; +import com.lagou.edu.utils.JsonUtils; +import com.lagou.edu.pojo.Result; +import com.lagou.edu.service.TransferService; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author 应癫 + */ +@WebServlet(name="transferServlet",urlPatterns = "/transferServlet") +public class TransferServlet extends HttpServlet { + + // 1. 实例化service层对象 + //private TransferService transferService = new TransferServiceImpl(); + //private TransferService transferService = (TransferService) BeanFactory.getBean("transferService"); + + // 从工厂获取委托对象(委托对象是增强了事务控制的功能) + + // 首先从BeanFactory获取到proxyFactory代理工厂的实例化对象 + private ProxyFactory proxyFactory = (ProxyFactory) AnnotationBeanFactory.getBean("proxyFactory"); + private TransferService transferService = (TransferService) proxyFactory.getJdkProxy(AnnotationBeanFactory.getBean("transferService")) ; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + doPost(req,resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + // 设置请求体的字符编码 + req.setCharacterEncoding("UTF-8"); + + String fromCardNo = req.getParameter("fromCardNo"); + String toCardNo = req.getParameter("toCardNo"); + String moneyStr = req.getParameter("money"); + int money = Integer.parseInt(moneyStr); + + Result result = new Result(); + + try { + + // 2. 调用service层方法 + transferService.transfer(fromCardNo,toCardNo,money); + result.setStatus("200"); + } catch (Exception e) { + e.printStackTrace(); + result.setStatus("201"); + result.setMessage(e.toString()); + } + + // 响应 + resp.setContentType("application/json;charset=utf-8"); + resp.getWriter().print(JsonUtils.object2Json(result)); + } +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/utils/ConnectionUtils.java b/code/lagou-transfer/src/main/java/com/lagou/edu/utils/ConnectionUtils.java new file mode 100755 index 0000000000000000000000000000000000000000..1f3a762f821aa9e39d378e3c5030da6d1938e0fc --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/utils/ConnectionUtils.java @@ -0,0 +1,44 @@ +package com.lagou.edu.utils; + +import com.lagou.edu.annotation.Repository; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author 应癫 + */ +@Repository +public class ConnectionUtils { + + /*private ConnectionUtils() { + + } + + private static ConnectionUtils connectionUtils = new ConnectionUtils(); + + public static ConnectionUtils getInstance() { + return connectionUtils; + }*/ + + + private ThreadLocal threadLocal = new ThreadLocal<>(); // 存储当前线程的连接 + + /** + * 从当前线程获取连接 + */ + public Connection getCurrentThreadConn() throws SQLException { + /** + * 判断当前线程中是否已经绑定连接,如果没有绑定,需要从连接池获取一个连接绑定到当前线程 + */ + Connection connection = threadLocal.get(); + if(connection == null) { + // 从连接池拿连接并绑定到线程 + connection = DruidUtils.getInstance().getConnection(); + // 绑定到当前线程 + threadLocal.set(connection); + } + return connection; + + } +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/utils/DruidUtils.java b/code/lagou-transfer/src/main/java/com/lagou/edu/utils/DruidUtils.java new file mode 100755 index 0000000000000000000000000000000000000000..f1657d93b0ca337da3925e554d29fcecb80d79b5 --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/utils/DruidUtils.java @@ -0,0 +1,28 @@ +package com.lagou.edu.utils; + +import com.alibaba.druid.pool.DruidDataSource; + +/** + * @author 应癫 + */ +public class DruidUtils { + + private DruidUtils(){ + } + + private static DruidDataSource druidDataSource = new DruidDataSource(); + + + static { + druidDataSource.setDriverClassName("com.mysql.jdbc.Driver"); + druidDataSource.setUrl("jdbc:mysql://localhost:3306/bank"); + druidDataSource.setUsername("root"); + druidDataSource.setPassword("7"); + + } + + public static DruidDataSource getInstance() { + return druidDataSource; + } + +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/utils/JsonUtils.java b/code/lagou-transfer/src/main/java/com/lagou/edu/utils/JsonUtils.java new file mode 100755 index 0000000000000000000000000000000000000000..dd20b02247328dcbb2f9b81692690c3ecedb5a92 --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/utils/JsonUtils.java @@ -0,0 +1,67 @@ +package com.lagou.edu.utils; + +import java.util.List; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * JSON工具类(使用的是jackson实现的) + * @author 应癫 + */ +public class JsonUtils { + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + /** + * 将对象转换成json字符串。 + * @param data + * @return + */ + public static String object2Json(Object data) { + try { + String string = MAPPER.writeValueAsString(data); + return string; + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 将json结果集转化为对象 + * + * @param jsonData json数据 + * @param beanType 对象中的object类型 + * @return + */ + public static T json2Pojo(String jsonData, Class beanType) { + try { + T t = MAPPER.readValue(jsonData, beanType); + return t; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 将json数据转换成pojo对象list + * @param jsonData + * @param beanType + * @return + */ + public static List json2List(String jsonData, Class beanType) { + JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType); + try { + List list = MAPPER.readValue(jsonData, javaType); + return list; + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + +} diff --git a/code/lagou-transfer/src/main/java/com/lagou/edu/utils/TransactionManager.java b/code/lagou-transfer/src/main/java/com/lagou/edu/utils/TransactionManager.java new file mode 100755 index 0000000000000000000000000000000000000000..2508036facde42a15a30285d1ec35c99542f7326 --- /dev/null +++ b/code/lagou-transfer/src/main/java/com/lagou/edu/utils/TransactionManager.java @@ -0,0 +1,51 @@ +package com.lagou.edu.utils; + +import com.lagou.edu.annotation.Autowired; +import com.lagou.edu.annotation.Repository; + +import java.sql.SQLException; + +/** + * @author 应癫 + * + * 事务管理器类:负责手动事务的开启、提交、回滚 + */ +@Repository +public class TransactionManager { + + @Autowired + private ConnectionUtils connectionUtils; + + public void setConnectionUtils(ConnectionUtils connectionUtils) { + this.connectionUtils = connectionUtils; + } + + /*private TransactionManager(){ + + } + + private static TransactionManager transactionManager = new TransactionManager(); + + public static TransactionManager getInstance() { + return transactionManager; + }*/ + + + + // 开启手动事务控制 + public void beginTransaction() throws SQLException { + connectionUtils.getCurrentThreadConn().setAutoCommit(false); + } + + + // 提交事务 + public void commit() throws SQLException { + connectionUtils.getCurrentThreadConn().commit(); + } + + + // 回滚事务 + public void rollback() throws SQLException { + connectionUtils.getCurrentThreadConn().rollback(); + } +} diff --git a/code/lagou-transfer/src/main/resources/beans.xml b/code/lagou-transfer/src/main/resources/beans.xml new file mode 100755 index 0000000000000000000000000000000000000000..6ec0912e1bcc2f071cc6d45bee1081712b8df8fe --- /dev/null +++ b/code/lagou-transfer/src/main/resources/beans.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/lagou-transfer/src/main/webapp/WEB-INF/web.xml b/code/lagou-transfer/src/main/webapp/WEB-INF/web.xml new file mode 100755 index 0000000000000000000000000000000000000000..9f88c1f9632445500e3b3688fe477b860f77d8f2 --- /dev/null +++ b/code/lagou-transfer/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Archetype Created Web Application + diff --git a/code/lagou-transfer/src/main/webapp/index.html b/code/lagou-transfer/src/main/webapp/index.html new file mode 100755 index 0000000000000000000000000000000000000000..cfd63b0d5d1cf43e804f70d7a187fc43c1d171a8 --- /dev/null +++ b/code/lagou-transfer/src/main/webapp/index.html @@ -0,0 +1,146 @@ + + + + + 转账汇款 + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + diff --git a/code/lagou-transfer/src/main/webapp/js/jquery-3.4.1.min.js b/code/lagou-transfer/src/main/webapp/js/jquery-3.4.1.min.js new file mode 100755 index 0000000000000000000000000000000000000000..a1c07fd803b5fc9c54f44e31123ae4fa11e134b0 --- /dev/null +++ b/code/lagou-transfer/src/main/webapp/js/jquery-3.4.1.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0