浏览代码

无功能调整

kangjie 5 年之前
父节点
当前提交
1cca39aeed
共有 44 个文件被更改,包括 1420 次插入360 次删除
  1. 0 92
      src/main/java/com/ssssssss/SqlFileListener.java
  2. 1 1
      src/main/java/com/ssssssss/TestApplication.java
  3. 56 0
      src/main/java/com/ssssssss/configuration/S8Configuration.java
  4. 24 0
      src/main/java/com/ssssssss/context/CookieContext.java
  5. 1 1
      src/main/java/com/ssssssss/context/HeaderContext.java
  6. 47 0
      src/main/java/com/ssssssss/context/RequestContext.java
  7. 19 0
      src/main/java/com/ssssssss/context/SessionContext.java
  8. 10 0
      src/main/java/com/ssssssss/dialect/Dialect.java
  9. 20 0
      src/main/java/com/ssssssss/dialect/DialectUtils.java
  10. 9 0
      src/main/java/com/ssssssss/dialect/MySqlDialect.java
  11. 5 0
      src/main/java/com/ssssssss/enums/SqlMode.java
  12. 8 0
      src/main/java/com/ssssssss/exception/S8Exception.java
  13. 9 0
      src/main/java/com/ssssssss/executor/ConnectionCallback.java
  14. 42 0
      src/main/java/com/ssssssss/executor/RequestExecutor.java
  15. 231 0
      src/main/java/com/ssssssss/executor/SqlExecutor.java
  16. 45 0
      src/main/java/com/ssssssss/executor/StatementExecutor.java
  17. 11 3
      src/main/java/com/ssssssss/expression/ExpressionEngine.java
  18. 3 0
      src/main/java/com/ssssssss/expression/parsing/Ast.java
  19. 4 0
      src/main/java/com/ssssssss/expression/parsing/Tokenizer.java
  20. 0 4
      src/main/java/com/ssssssss/handler/CookieContext.java
  21. 0 20
      src/main/java/com/ssssssss/handler/RequestContext.java
  22. 0 97
      src/main/java/com/ssssssss/handler/RequestHandler.java
  23. 0 11
      src/main/java/com/ssssssss/handler/SessionContext.java
  24. 0 78
      src/main/java/com/ssssssss/mapping/SqlMappingManager.java
  25. 53 0
      src/main/java/com/ssssssss/model/JsonBean.java
  26. 32 0
      src/main/java/com/ssssssss/model/Page.java
  27. 34 0
      src/main/java/com/ssssssss/model/PageResult.java
  28. 0 49
      src/main/java/com/ssssssss/model/SqlMapping.java
  29. 10 0
      src/main/java/com/ssssssss/provider/PageProvider.java
  30. 40 0
      src/main/java/com/ssssssss/provider/impl/DefaultPageProvider.java
  31. 67 0
      src/main/java/com/ssssssss/scripts/ForeachSqlNode.java
  32. 26 0
      src/main/java/com/ssssssss/scripts/IfSqlNode.java
  33. 41 0
      src/main/java/com/ssssssss/scripts/SqlNode.java
  34. 36 0
      src/main/java/com/ssssssss/scripts/TextSqlNode.java
  35. 100 0
      src/main/java/com/ssssssss/session/Configuration.java
  36. 77 0
      src/main/java/com/ssssssss/session/SqlStatement.java
  37. 40 0
      src/main/java/com/ssssssss/session/XMLStatement.java
  38. 30 0
      src/main/java/com/ssssssss/utils/Assert.java
  39. 165 0
      src/main/java/com/ssssssss/utils/S8XMLFileParser.java
  40. 51 0
      src/main/java/com/ssssssss/utils/XmlFileLoader.java
  41. 2 2
      src/main/resources/application.properties
  42. 0 1
      src/main/resources/ssssssss/role/list.sql
  43. 71 0
      src/main/resources/ssssssss/role/test.xml
  44. 0 1
      src/main/resources/ssssssss/test/select.sql

+ 0 - 92
src/main/java/com/ssssssss/SqlFileListener.java

@@ -1,92 +0,0 @@
-package com.ssssssss;
-
-import com.ssssssss.mapping.SqlMappingManager;
-import org.apache.commons.io.monitor.FileAlterationListener;
-import org.apache.commons.io.monitor.FileAlterationMonitor;
-import org.apache.commons.io.monitor.FileAlterationObserver;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.PostConstruct;
-import java.io.File;
-import java.net.URL;
-
-@Component
-public class SqlFileListener implements FileAlterationListener {
-
-    @Autowired
-    private SqlMappingManager manager;
-
-    @Value("${ssssssss.directory:/ssssssss}")
-    private String directory;
-
-    @PostConstruct
-    private void init(){
-        new Thread(()->{
-            try {
-                File file = new File(SqlFileListener.class.getResource(this.directory).getFile());
-                SqlFileListener.this.directory = file.getPath();
-                start(file.listFiles());
-                FileAlterationObserver observer = new FileAlterationObserver(file);
-                observer.addListener(SqlFileListener.this);
-                new FileAlterationMonitor(50,observer).start();
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }).start();
-    }
-
-
-    @Override
-    public void onStart(FileAlterationObserver observer) {
-
-    }
-
-    private void start(File[] files){
-        if(files != null){
-            for (File file : files) {
-                if(file.isFile()){
-                    manager.register(this.directory,file);
-                }else{
-                    start(file.listFiles());
-                }
-            }
-        }
-    }
-
-    @Override
-    public void onDirectoryCreate(File directory) {
-
-    }
-
-    @Override
-    public void onDirectoryChange(File directory) {
-
-    }
-
-    @Override
-    public void onDirectoryDelete(File directory) {
-
-    }
-
-    @Override
-    public void onFileCreate(File file) {
-        manager.register(this.directory,file);
-    }
-
-    @Override
-    public void onFileChange(File file) {
-        manager.register(this.directory,file);
-    }
-
-    @Override
-    public void onFileDelete(File file) {
-        manager.unregister(this.directory,file);
-    }
-
-    @Override
-    public void onStop(FileAlterationObserver observer) {
-
-    }
-}

+ 1 - 1
src/main/java/com/ssssssss/TestApplication.java

@@ -7,7 +7,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
 public class TestApplication {
 
 
-    public static void main(String[] args) throws InterruptedException {
+    public static void main(String[] args) {
         SpringApplication.run(TestApplication.class);
     }
 }

+ 56 - 0
src/main/java/com/ssssssss/configuration/S8Configuration.java

@@ -0,0 +1,56 @@
+package com.ssssssss.configuration;
+
+import com.ssssssss.executor.RequestExecutor;
+import com.ssssssss.executor.SqlExecutor;
+import com.ssssssss.executor.StatementExecutor;
+import com.ssssssss.expression.ExpressionEngine;
+import com.ssssssss.provider.PageProvider;
+import com.ssssssss.provider.impl.DefaultPageProvider;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.sql.DataSource;
+
+@Configuration
+public class S8Configuration {
+
+    @Bean
+    public RequestExecutor requestExecutor() {
+        return new RequestExecutor();
+    }
+
+    @Bean
+    public ExpressionEngine expressionEngine() {
+        return new ExpressionEngine();
+    }
+
+    @ConditionalOnMissingBean(PageProvider.class)
+    @Bean
+    public PageProvider pageProvider(){
+        return new DefaultPageProvider("page","size");
+    }
+
+    @Bean
+    public StatementExecutor statementExecutor(DataSource dataSource,PageProvider pageProvider) {
+        SqlExecutor sqlExecutor = new SqlExecutor(dataSource);
+        sqlExecutor.setMapUnderscoreToCamelCase(true);
+        return new StatementExecutor(sqlExecutor, pageProvider);
+    }
+
+    @Bean
+    public com.ssssssss.session.Configuration configuration(StatementExecutor statementExecutor, ExpressionEngine expressionEngine, RequestExecutor requestExecutor, RequestMappingHandlerMapping requestMappingHandlerMapping) throws NoSuchMethodException {
+        com.ssssssss.session.Configuration configuration = new com.ssssssss.session.Configuration();
+        configuration.setRequestMappingHandlerMapping(requestMappingHandlerMapping);
+        configuration.setRequestHandler(requestExecutor);
+        configuration.setXmlLocations("classpath*:ssssssss/*/**.xml");
+        configuration.setEnableRefresh(true);
+        configuration.setRequestHandleMethod(RequestExecutor.class.getDeclaredMethod("invoke", HttpServletRequest.class));
+        requestExecutor.setConfiguration(configuration);
+        requestExecutor.setExpressionEngine(expressionEngine);
+        requestExecutor.setStatementExecutor(statementExecutor);
+        return configuration;
+    }
+}

+ 24 - 0
src/main/java/com/ssssssss/context/CookieContext.java

@@ -0,0 +1,24 @@
+package com.ssssssss.context;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+
+public class CookieContext extends HashMap<String,String> {
+
+    private Cookie[] cookies;
+
+    public CookieContext(HttpServletRequest request){
+        this.cookies = request.getCookies();
+    }
+
+    @Override
+    public String get(Object key) {
+        for (int i = 0; i < cookies.length; i++) {
+            if(cookies[i].getName().equalsIgnoreCase("" + key)){
+                return cookies[i].getValue();
+            }
+        }
+        return null;
+    }
+}

+ 1 - 1
src/main/java/com/ssssssss/handler/HeaderContext.java → src/main/java/com/ssssssss/context/HeaderContext.java

@@ -1,4 +1,4 @@
-package com.ssssssss.handler;
+package com.ssssssss.context;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.HashMap;

+ 47 - 0
src/main/java/com/ssssssss/context/RequestContext.java

@@ -0,0 +1,47 @@
+package com.ssssssss.context;
+
+import com.ssssssss.expression.ExpressionEngine;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+
+public class RequestContext extends HashMap<String,Object> {
+
+    private HttpServletRequest request;
+
+    private List<Object> parameters = new ArrayList<>();
+
+    private ExpressionEngine engine;
+
+    public RequestContext(HttpServletRequest request,ExpressionEngine engine) {
+        this.request = request;
+        this.engine = engine;
+        Enumeration<String> parameterNames = request.getParameterNames();
+        while (parameterNames.hasMoreElements()){
+            String key = parameterNames.nextElement();
+            put(key,request.getParameter(key));
+        }
+        put("header",new HeaderContext(request));
+        put("cookie",new CookieContext(request));
+        put("session",new SessionContext(request.getSession()));
+    }
+
+    public HttpServletRequest getRequest() {
+        return request;
+    }
+
+    public void addParameter(Object value){
+        this.parameters.add(value);
+    }
+
+    public List<Object> getParameters() {
+        return parameters;
+    }
+
+    public Object evaluate(String expression){
+        return engine.executeWrap(expression,this);
+    }
+}

+ 19 - 0
src/main/java/com/ssssssss/context/SessionContext.java

@@ -0,0 +1,19 @@
+package com.ssssssss.context;
+
+import javax.servlet.http.HttpSession;
+import java.util.HashMap;
+import java.util.Objects;
+
+public class SessionContext extends HashMap<String,Object> {
+
+    private HttpSession session;
+
+    public SessionContext(HttpSession session){
+        this.session = session;
+    }
+
+    @Override
+    public Object get(Object key) {
+        return session.getAttribute(key.toString());
+    }
+}

+ 10 - 0
src/main/java/com/ssssssss/dialect/Dialect.java

@@ -0,0 +1,10 @@
+package com.ssssssss.dialect;
+
+public interface Dialect {
+
+    default String getCountSql(String sql) {
+        return "select count(1) from (" + sql + ") count_";
+    }
+
+    String getPageSql(String sql, long offset, long limit);
+}

+ 20 - 0
src/main/java/com/ssssssss/dialect/DialectUtils.java

@@ -0,0 +1,20 @@
+package com.ssssssss.dialect;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class DialectUtils {
+
+    private static Map<String, Dialect> dialectMap = new ConcurrentHashMap<>();
+
+    public static Dialect getDialectFromUrl(String fromUrl) {
+        Dialect dialect = dialectMap.get(fromUrl);
+        if (dialect == null) {
+            if (fromUrl.startsWith("jdbc:mysql:") || fromUrl.startsWith("jdbc:cobar:") || fromUrl.startsWith("jdbc:log4jdbc:mysql:")) {
+                dialect = new MySqlDialect();
+            }
+            dialectMap.put(fromUrl, dialect);
+        }
+        return dialect;
+    }
+}

+ 9 - 0
src/main/java/com/ssssssss/dialect/MySqlDialect.java

@@ -0,0 +1,9 @@
+package com.ssssssss.dialect;
+
+public class MySqlDialect implements Dialect {
+
+    @Override
+    public String getPageSql(String sql, long offset, long limit) {
+        return sql + " limit ?,?";
+    }
+}

+ 5 - 0
src/main/java/com/ssssssss/enums/SqlMode.java

@@ -0,0 +1,5 @@
+package com.ssssssss.enums;
+
+public enum SqlMode {
+    SELECT_LIST,SELECT_ONE,SELECT_NUMBER,UPDATE,INSERT,DELETE
+}

+ 8 - 0
src/main/java/com/ssssssss/exception/S8Exception.java

@@ -0,0 +1,8 @@
+package com.ssssssss.exception;
+
+public class S8Exception extends RuntimeException{
+
+    public S8Exception(String message) {
+        super(message);
+    }
+}

+ 9 - 0
src/main/java/com/ssssssss/executor/ConnectionCallback.java

@@ -0,0 +1,9 @@
+package com.ssssssss.executor;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+public interface ConnectionCallback<T> {
+
+    T execute(Connection connection) throws SQLException;
+}

+ 42 - 0
src/main/java/com/ssssssss/executor/RequestExecutor.java

@@ -0,0 +1,42 @@
+package com.ssssssss.executor;
+
+import com.ssssssss.context.RequestContext;
+import com.ssssssss.expression.ExpressionEngine;
+import com.ssssssss.model.JsonBean;
+import com.ssssssss.session.Configuration;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import java.sql.SQLException;
+
+public class RequestExecutor {
+
+    private Configuration configuration;
+
+    private StatementExecutor statementExecutor;
+
+    private ExpressionEngine expressionEngine;
+
+    public void setConfiguration(Configuration configuration) {
+        this.configuration = configuration;
+    }
+
+    public void setStatementExecutor(StatementExecutor statementExecutor) {
+        this.statementExecutor = statementExecutor;
+    }
+
+    public void setExpressionEngine(ExpressionEngine expressionEngine) {
+        this.expressionEngine = expressionEngine;
+    }
+
+    @ResponseBody
+    public Object invoke(HttpServletRequest request) throws SQLException {
+        RequestContext requestContext = new RequestContext(request,expressionEngine);
+        String requestMapping = request.getServletPath();
+        if (requestMapping.endsWith("/")) {
+            requestMapping = requestMapping.substring(0, requestMapping.length() - 1);
+        }
+        Object value = statementExecutor.execute(configuration.getStatement(requestMapping), requestContext);
+        return new JsonBean<>(value);
+    }
+}

+ 231 - 0
src/main/java/com/ssssssss/executor/SqlExecutor.java

@@ -0,0 +1,231 @@
+package com.ssssssss.executor;
+
+import com.ssssssss.enums.SqlMode;
+import com.ssssssss.exception.S8Exception;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.sql.DataSource;
+import java.sql.*;
+import java.util.Date;
+import java.util.*;
+
+public class SqlExecutor {
+
+    private DataSource dataSource;
+
+    private Logger logger = LoggerFactory.getLogger(SqlExecutor.class);
+
+    /**
+     * 是否启用驼峰命名
+     */
+    private boolean mapUnderscoreToCamelCase;
+
+    public SqlExecutor(DataSource dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    public void setMapUnderscoreToCamelCase(boolean mapUnderscoreToCamelCase) {
+        this.mapUnderscoreToCamelCase = mapUnderscoreToCamelCase;
+    }
+
+    public Object execute(SqlMode mode, String sql, List<Object> parameters, Class<?> returnType) throws SQLException {
+        if (SqlMode.SELECT_LIST == mode) {
+            return queryForList(sql, parameters, returnType == null ? Map.class : returnType);
+        } else if (SqlMode.UPDATE == mode || SqlMode.INSERT == mode || SqlMode.DELETE == mode) {
+            return update(sql, parameters);
+        } else if (SqlMode.SELECT_ONE == mode) {
+            return queryForOne(sql, parameters, returnType);
+        } else if (SqlMode.SELECT_NUMBER == mode) {
+            return queryForNumber(sql, parameters, returnType);
+        } else {
+            throw new S8Exception("暂时不支持[" + mode + "]模式");
+        }
+    }
+
+    private Connection getConnection() throws SQLException {
+        return dataSource.getConnection();
+    }
+
+    public <T> T doInConnection(ConnectionCallback<T> connectionCallback) throws SQLException {
+        Connection connection = getConnection();
+        try {
+            return connectionCallback.execute(connection);
+        } finally {
+            closeConnection(connection);
+        }
+    }
+
+    private int update(String sql, List<Object> params) throws SQLException {
+        Connection connection = getConnection();
+        PreparedStatement stmt = null;
+        try {
+            stmt = createPreparedStatement(connection, sql, params);
+            return stmt.executeUpdate();
+        } finally {
+            closeStatement(stmt);
+            closeConnection(connection);
+        }
+    }
+
+    private <T> T queryForNumber(String sql, List<Object> params, Class<T> returnType) throws SQLException {
+        Connection conn = getConnection();
+        try {
+            return queryForNumber(conn, sql, params, returnType);
+        } finally {
+            closeConnection(conn);
+        }
+    }
+
+    public <T> T queryForNumber(Connection connection, String sql, List<Object> params, Class<T> returnType) throws SQLException {
+        PreparedStatement stmt = null;
+        ResultSet rs = null;
+        try {
+            stmt = createPreparedStatement(connection, sql, params);
+            rs = stmt.executeQuery();
+            if (rs.next()) {
+                return rs.getObject(1, returnType);
+            }
+        } finally {
+            closeResultSet(rs);
+            closeStatement(stmt);
+        }
+        return null;
+    }
+
+    private Object queryForOne(String sql, List<Object> params, Class<?> returnType) throws SQLException {
+        Connection connection = getConnection();
+        PreparedStatement stmt = null;
+        ResultSet rs = null;
+        try {
+            stmt = createPreparedStatement(connection, sql, params);
+            rs = stmt.executeQuery();
+            if (returnType == null || returnType == Map.class) {
+                ResultSetMetaData rsd = rs.getMetaData();
+                int columnCount = rsd.getColumnCount();
+                if (rs.next()) {
+                    return fetchResultSet(rs);
+                }
+            } else if (rs.next()) {
+                return rs.getObject(1, returnType);
+            }
+        } finally {
+            closeResultSet(rs);
+            closeStatement(stmt);
+            closeConnection(connection);
+        }
+        return null;
+    }
+
+    public List<Object> queryForList(Connection connection, String sql, List<Object> params, Class<?> returnType) throws SQLException {
+        PreparedStatement stmt = null;
+        ResultSet rs = null;
+        try {
+            stmt = createPreparedStatement(connection, sql, params);
+            rs = stmt.executeQuery();
+            List<Object> list = new ArrayList<>();
+            if (returnType == null || returnType == Map.class) {
+                while (rs.next()) {
+                    list.add(fetchResultSet(rs));
+                }
+            } else {
+                while (rs.next()) {
+                    list.add(rs.getObject(1, returnType));
+                }
+            }
+            return list;
+        } finally {
+            closeResultSet(rs);
+            closeStatement(stmt);
+        }
+    }
+
+    private Map<String,Object> fetchResultSet(ResultSet rs) throws SQLException {
+        ResultSetMetaData rsd = rs.getMetaData();
+        int columnCount = rsd.getColumnCount();
+        Map<String,Object> row = new HashMap<>(columnCount);
+        for (int i = 1; i <= columnCount; i++) {
+            row.put(underscoreToCamelCase(rsd.getColumnName(i)), rs.getObject(i));
+        }
+        return row;
+    }
+
+    private String underscoreToCamelCase(String columnName){
+        if(mapUnderscoreToCamelCase){
+            columnName = columnName.toLowerCase();
+            boolean upperCase = false;
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < columnName.length(); i++) {
+                char ch = columnName.charAt(i);
+                if (ch == '_') {
+                    upperCase = true;
+                } else if (upperCase) {
+                    sb.append(Character.toUpperCase(ch));
+                    upperCase = false;
+                } else {
+                    sb.append(ch);
+                }
+            }
+            columnName = sb.toString();
+        }
+        return columnName;
+    }
+
+    private List<Object> queryForList(String sql, List<Object> params, Class<?> returnType) throws SQLException {
+        Connection connection = getConnection();
+        try {
+            return queryForList(connection, sql, params, returnType);
+        } finally {
+            closeConnection(connection);
+        }
+    }
+
+    private PreparedStatement createPreparedStatement(Connection conn, String sql, List<Object> params) throws SQLException {
+        PreparedStatement stmt = conn.prepareStatement(sql);
+        logger.debug("执行SQL:{}",sql);
+        setStatementParams(stmt, params);
+        return stmt;
+    }
+
+    private void setStatementParams(PreparedStatement stmt, List<Object> params) throws SQLException {
+        if (params != null) {
+            logger.debug("sql参数:{}",params);
+            for (int i = 0; i < params.size(); i++) {
+                Object val = params.get(i);
+                if (val instanceof Date) {
+                    stmt.setTimestamp(i + 1, new java.sql.Timestamp(((Date) val).getTime()));
+                } else {
+                    stmt.setObject(i + 1, val);
+                }
+            }
+        }
+    }
+
+
+    private void closeConnection(Connection connection) {
+        if (connection != null) {
+            try {
+                connection.close();
+            } catch (SQLException ignored) {
+            }
+        }
+    }
+
+    private void closeResultSet(ResultSet resultSet) {
+        if (resultSet != null) {
+            try {
+                resultSet.close();
+            } catch (SQLException ignored) {
+            }
+        }
+    }
+
+    private void closeStatement(Statement statement) {
+        if (statement != null) {
+            try {
+                statement.close();
+            } catch (SQLException ignored) {
+            }
+        }
+    }
+}

+ 45 - 0
src/main/java/com/ssssssss/executor/StatementExecutor.java

@@ -0,0 +1,45 @@
+package com.ssssssss.executor;
+
+import com.ssssssss.context.RequestContext;
+import com.ssssssss.dialect.Dialect;
+import com.ssssssss.dialect.DialectUtils;
+import com.ssssssss.model.Page;
+import com.ssssssss.model.PageResult;
+import com.ssssssss.provider.PageProvider;
+import com.ssssssss.session.SqlStatement;
+
+import java.sql.SQLException;
+
+public class StatementExecutor {
+
+    private SqlExecutor sqlExecutor;
+
+    private PageProvider pageProvider;
+
+    public StatementExecutor(SqlExecutor sqlExecutor, PageProvider pageProvider) {
+        this.sqlExecutor = sqlExecutor;
+        this.pageProvider = pageProvider;
+    }
+
+    public Object execute(SqlStatement sqlStatement, RequestContext context) throws SQLException {
+        String sql = sqlStatement.getSqlNode().getSql(context).trim();
+        if(sqlStatement.isPagination()){
+            Page page = pageProvider.getPage(context.getRequest());
+            return sqlExecutor.doInConnection(connection -> {
+                PageResult<Object> pageResult = new PageResult<>();
+                Dialect dialect = DialectUtils.getDialectFromUrl(connection.getMetaData().getURL());
+                long total = sqlExecutor.queryForNumber(connection,dialect.getCountSql(sql),context.getParameters(),Long.class);
+                pageResult.setTotal(total);
+                if(total > 0){
+                    String pageSql = dialect.getPageSql(sql, page.getOffset(), page.getLimit());
+                    context.addParameter(page.getLimit());
+                    context.addParameter(page.getOffset());
+                    pageResult.setList(sqlExecutor.queryForList(connection,pageSql,context.getParameters(),sqlStatement.getReturnType()));
+                }
+                return pageResult;
+            });
+        }else{
+            return sqlExecutor.execute(sqlStatement.getSqlMode(), sql, context.getParameters(), sqlStatement.getReturnType());
+        }
+    }
+}

+ 11 - 3
src/main/java/com/ssssssss/expression/DefaultExpressionEngine.java → src/main/java/com/ssssssss/expression/ExpressionEngine.java

@@ -1,19 +1,21 @@
 package com.ssssssss.expression;
 
+<<<<<<< HEAD:src/main/java/com/ssssssss/expression/DefaultExpressionEngine.java
 import org.springframework.stereotype.Component;
 
 import java.util.HashMap;
+=======
+>>>>>>> bea407944d46c13c7683b957cafd4061088611a7:src/main/java/com/ssssssss/expression/ExpressionEngine.java
 import java.util.Map;
 
-@Component
-public class DefaultExpressionEngine {
-	
+public class ExpressionEngine {
 
 	public Object execute(String expression, Map<String, Object> variables) {
 		ExpressionTemplateContext context = new ExpressionTemplateContext(variables);
 		return ExpressionTemplate.create(expression).render(context);
 	}
 
+<<<<<<< HEAD:src/main/java/com/ssssssss/expression/DefaultExpressionEngine.java
 	public static void main(String[] args) {
 
 		DefaultExpressionEngine engine = new DefaultExpressionEngine();
@@ -25,4 +27,10 @@ public class DefaultExpressionEngine {
 
 	}
 	
+=======
+	public Object executeWrap(String expression, Map<String, Object> variables) {
+		return execute("${" + expression + "}", variables);
+	}
+
+>>>>>>> bea407944d46c13c7683b957cafd4061088611a7:src/main/java/com/ssssssss/expression/ExpressionEngine.java
 }

+ 3 - 0
src/main/java/com/ssssssss/expression/parsing/Ast.java

@@ -377,6 +377,9 @@ public abstract class Ast {
 		}
 
 		private Object evaluateGreater (Object left, Object right) {
+			if(left == null || right == null){
+				return false;
+			}
 			if (left instanceof Double || right instanceof Double) {
 				return ((Number)left).doubleValue() > ((Number)right).doubleValue();
 			} else if (left instanceof Float || right instanceof Float) {

+ 4 - 0
src/main/java/com/ssssssss/expression/parsing/Tokenizer.java

@@ -178,6 +178,10 @@ public class Tokenizer {
 					tokens.add(new Token(TokenType.BooleanLiteral, identifierSpan));
 				} else if ("null".equals(identifierSpan.getText())) {
 					tokens.add(new Token(TokenType.NullLiteral, identifierSpan));
+				} else if (identifierSpan.getText().equals("and")) {
+					tokens.add(new Token(TokenType.And,identifierSpan));
+				} else if (identifierSpan.getText().equals("or")) {
+					tokens.add(new Token(TokenType.Or,identifierSpan));
 				} else {
 					tokens.add(new Token(TokenType.Identifier, identifierSpan));
 				}

+ 0 - 4
src/main/java/com/ssssssss/handler/CookieContext.java

@@ -1,4 +0,0 @@
-package com.ssssssss.handler;
-
-public class CookieContext {
-}

+ 0 - 20
src/main/java/com/ssssssss/handler/RequestContext.java

@@ -1,20 +0,0 @@
-package com.ssssssss.handler;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.Enumeration;
-import java.util.HashMap;
-
-public class RequestContext extends HashMap<String,Object> {
-
-    private HttpServletRequest request;
-
-    public RequestContext(HttpServletRequest request) {
-        this.request = request;
-        Enumeration<String> parameterNames = request.getParameterNames();
-        while (parameterNames.hasMoreElements()){
-            String key = parameterNames.nextElement();
-            put(key,request.getParameter(key));
-        }
-        put("header",new HeaderContext(request));
-    }
-}

+ 0 - 97
src/main/java/com/ssssssss/handler/RequestHandler.java

@@ -1,97 +0,0 @@
-package com.ssssssss.handler;
-
-import com.ssssssss.expression.DefaultExpressionEngine;
-import com.ssssssss.mapping.SqlMappingManager;
-import com.ssssssss.model.SqlMapping;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.stereotype.Component;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-@Component
-public class RequestHandler {
-
-    @Autowired
-    private SqlMappingManager manager;
-
-    @Autowired
-    private JdbcTemplate template;
-
-    private Pattern optionRegx = Pattern.compile("\\[(.*?)\\]");
-
-    private Pattern expressionRegx = Pattern.compile("#\\{(.*?)\\}");
-
-    @ResponseBody
-    public Object request(HttpServletRequest request) {
-        String mapping = request.getServletPath();
-        if(mapping.endsWith("/")){
-            mapping = mapping.substring(0,mapping.length() - 1);
-        }
-        SqlMapping sqlMapping = manager.getSqlMapping(mapping);
-        return invoke(sqlMapping,new RequestContext(request));
-    }
-
-    private Object invoke(SqlMapping sqlMapping, Map<String,Object> context){
-        String sql = sqlMapping.getSql();
-        List<String> options = extract(sql, optionRegx);
-        DefaultExpressionEngine engine = new DefaultExpressionEngine();
-        List<Object> params = new ArrayList<>();
-        Map<String,Object> cachedValues = new HashMap<>();
-        for (String option : options) {
-            List<String> expressions = extract(option, expressionRegx);
-            boolean hasNull = false;
-            for (String expression : expressions) {
-                Object val = engine.execute("${" + expression + "}", context);
-                cachedValues.put(expression,val);
-                if(val == null){
-                    hasNull = true;
-                    break;
-                }
-            }
-            sql = sql.replaceFirst(optionRegx.pattern() ,hasNull ? "":"$1");
-        }
-        List<String> expressions = extract(sql, expressionRegx);
-        for (String expression : expressions) {
-            Object val = cachedValues.get(expression);
-            if(!cachedValues.containsKey(expression)){
-                val = engine.execute("${" + expression + "}", context);
-            }
-            sql = sql.replaceFirst(expressionRegx.pattern(),"?");
-            params.add(val);
-        }
-        System.out.println(sql);
-        System.out.println(params);
-        if(params.size() == 0){
-            return template.queryForList(sql);
-        }
-        return template.queryForList(sql,params.toArray());
-    }
-
-    public List<String> extract(String sql, Pattern pattern){
-        Matcher matcher = pattern.matcher(sql);
-        List<String> results = new ArrayList<>();
-        while(matcher.find()){
-            results.add(matcher.group(1));
-        }
-        return results;
-    }
-
-    public static void main(String[] args) {
-        String sql = "select * from sys_user where user_id = #{userId} [and user_name = #{userName.substring(2)}] and abc = #{abc}";
-        SqlMapping mapping = new SqlMapping(sql,null,null);
-        new RequestHandler().invoke(mapping,new HashMap<String,Object>(){
-            {
-                put("userId","123");
-               // put("userName","abcd");
-            }
-        });
-    }
-}

+ 0 - 11
src/main/java/com/ssssssss/handler/SessionContext.java

@@ -1,11 +0,0 @@
-package com.ssssssss.handler;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import java.util.HashMap;
-
-public class SessionContext {
-
-    private HttpServletRequest request;
-
-}

+ 0 - 78
src/main/java/com/ssssssss/mapping/SqlMappingManager.java

@@ -1,78 +0,0 @@
-package com.ssssssss.mapping;
-
-import com.ssssssss.handler.RequestHandler;
-import com.ssssssss.model.SqlMapping;
-import org.apache.commons.io.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
-import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
-
-import javax.servlet.http.HttpServletRequest;
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-
-@Component
-public class SqlMappingManager {
-
-    private static Logger logger = LoggerFactory.getLogger(SqlMappingManager.class);
-
-    private Map<String, SqlMapping> sqlMaps = new HashMap<>();
-
-    private Method requestInvokeMethod = RequestHandler.class.getDeclaredMethod("request", HttpServletRequest.class);
-
-    @Autowired
-    private RequestHandler requestInvokeHandler;
-
-    @Autowired
-    private RequestMappingHandlerMapping requestMappingHandlerMapping;
-
-    public SqlMappingManager() throws NoSuchMethodException {
-    }
-
-
-    public void register(String directory,File file){
-        String mapping = convertToRequestMapping(directory, file.getPath());
-        try {
-            String sql = FileUtils.readFileToString(file,"UTF-8");
-            boolean hasRegisted = sqlMaps.containsKey(mapping);
-            sqlMaps.put(mapping,new SqlMapping(sql,mapping,file.getPath()));
-            if(!hasRegisted){
-                logger.info("注册{}",mapping);
-                requestMappingHandlerMapping.registerMapping(RequestMappingInfo.paths(mapping).build(),requestInvokeHandler,requestInvokeMethod);
-            }else{
-                logger.info("刷新{}",mapping);
-            }
-
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    public void unregister(String directory,File file){
-        String mapping = convertToRequestMapping(directory, file.getPath());
-        logger.info("取消注册{}",mapping);
-        sqlMaps.remove(mapping);
-        requestMappingHandlerMapping.unregisterMapping(RequestMappingInfo.paths(mapping).build());
-    }
-
-    public SqlMapping getSqlMapping(String mapping){
-        return sqlMaps.get(mapping);
-    }
-
-    private String convertToRequestMapping(String dir,String file){
-        String mapping = file.substring(dir.length());
-        int index = mapping.lastIndexOf(".");
-        if(index > -1){
-            mapping = mapping.substring(0,index);
-        }
-        mapping = mapping.replace("\\","/");
-        return mapping;
-    }
-
-}

+ 53 - 0
src/main/java/com/ssssssss/model/JsonBean.java

@@ -0,0 +1,53 @@
+package com.ssssssss.model;
+
+public class JsonBean<T> {
+
+    private int code = 1;
+
+    private String message = "success";
+
+    private T data;
+
+    private long timestamp = System.currentTimeMillis();
+
+    public JsonBean(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public JsonBean(T data) {
+        this.data = data;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+}

+ 32 - 0
src/main/java/com/ssssssss/model/Page.java

@@ -0,0 +1,32 @@
+package com.ssssssss.model;
+
+public class Page {
+
+    private long limit;
+
+    private long offset;
+
+    public Page() {
+    }
+
+    public Page(long limit, long offset) {
+        this.limit = limit;
+        this.offset = offset;
+    }
+
+    public long getLimit() {
+        return limit;
+    }
+
+    public void setLimit(long limit) {
+        this.limit = limit;
+    }
+
+    public long getOffset() {
+        return offset;
+    }
+
+    public void setOffset(long offset) {
+        this.offset = offset;
+    }
+}

+ 34 - 0
src/main/java/com/ssssssss/model/PageResult.java

@@ -0,0 +1,34 @@
+package com.ssssssss.model;
+
+import java.util.List;
+
+public class PageResult<T> {
+
+    private long total;
+
+    private List<T> list;
+
+    public PageResult(long total, List<T> list) {
+        this.total = total;
+        this.list = list;
+    }
+
+    public PageResult() {
+    }
+
+    public long getTotal() {
+        return total;
+    }
+
+    public void setTotal(long total) {
+        this.total = total;
+    }
+
+    public List<T> getList() {
+        return list;
+    }
+
+    public void setList(List<T> list) {
+        this.list = list;
+    }
+}

+ 0 - 49
src/main/java/com/ssssssss/model/SqlMapping.java

@@ -1,49 +0,0 @@
-package com.ssssssss.model;
-
-public class SqlMapping {
-
-    /**
-     * SQL语句
-     */
-    private String sql;
-
-    /**
-     * 访问路径
-     */
-    private String path;
-
-    /**
-     * 文件路径
-     */
-    private String file;
-
-    public SqlMapping(String sql, String path, String file) {
-        this.sql = sql;
-        this.path = path;
-        this.file = file;
-    }
-
-    public String getSql() {
-        return sql;
-    }
-
-    public void setSql(String sql) {
-        this.sql = sql;
-    }
-
-    public String getPath() {
-        return path;
-    }
-
-    public void setPath(String path) {
-        this.path = path;
-    }
-
-    public String getFile() {
-        return file;
-    }
-
-    public void setFile(String file) {
-        this.file = file;
-    }
-}

+ 10 - 0
src/main/java/com/ssssssss/provider/PageProvider.java

@@ -0,0 +1,10 @@
+package com.ssssssss.provider;
+
+import com.ssssssss.model.Page;
+
+import javax.servlet.http.HttpServletRequest;
+
+public interface PageProvider {
+
+    public Page getPage(HttpServletRequest request);
+}

+ 40 - 0
src/main/java/com/ssssssss/provider/impl/DefaultPageProvider.java

@@ -0,0 +1,40 @@
+package com.ssssssss.provider.impl;
+
+import com.ssssssss.model.Page;
+import com.ssssssss.provider.PageProvider;
+import org.apache.commons.lang3.math.NumberUtils;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class DefaultPageProvider implements PageProvider {
+
+    private String pageName;
+
+    private String pageSize;
+
+    private long defaultPageSize = 10;
+
+    private long defaultPage = 1;
+
+    public DefaultPageProvider(String pageName, String pageSize) {
+        this.pageName = pageName;
+        this.pageSize = pageSize;
+    }
+
+    public DefaultPageProvider(String pageName, String pageSize, long defaultPageSize, long defaultPage) {
+        this.pageName = pageName;
+        this.pageSize = pageSize;
+        this.defaultPageSize = defaultPageSize;
+        this.defaultPage = defaultPage;
+    }
+
+
+
+    @Override
+    public Page getPage(HttpServletRequest request) {
+        long page = NumberUtils.toLong(request.getParameter(this.pageName), this.defaultPage);
+        long pageSize = NumberUtils.toLong(request.getParameter(this.pageSize), this.defaultPageSize);
+        return new Page((page - 1) * pageSize, pageSize);
+
+    }
+}

+ 67 - 0
src/main/java/com/ssssssss/scripts/ForeachSqlNode.java

@@ -0,0 +1,67 @@
+package com.ssssssss.scripts;
+
+import com.ssssssss.context.RequestContext;
+import org.apache.commons.lang3.StringUtils;
+
+import java.lang.reflect.Array;
+import java.util.Collection;
+
+/**
+ * 对应XML中 <foreach>
+ */
+public class ForeachSqlNode extends SqlNode{
+
+    private String collection;
+
+    private String item;
+
+    private String open;
+
+    private String close;
+
+    private String separator;
+
+    public void setCollection(String collection) {
+        this.collection = collection;
+    }
+
+    public void setItem(String item) {
+        this.item = item;
+    }
+
+    public void setOpen(String open) {
+        this.open = open;
+    }
+
+    public void setClose(String close) {
+        this.close = close;
+    }
+
+    public void setSeparator(String separator) {
+        this.separator = separator;
+    }
+
+    @Override
+    public String getSql(RequestContext context) {
+        Object value = context.evaluate(this.collection);
+        if(value == null){
+            return "";
+        }
+        String sql = StringUtils.defaultString(this.open);
+        if(value instanceof Collection){
+            value = ((Collection) value).toArray();
+        }
+        if(value.getClass().isArray()){
+            int len = Array.getLength(value);
+            for (int i = 0; i < len; i++) {
+                context.put(this.item,Array.get(value,i));
+                sql += executeChildren(context);
+                if(i + 1 < len){
+                    sql += StringUtils.defaultString(this.separator);
+                }
+            }
+        }
+        sql+=StringUtils.defaultString(this.close);
+        return sql;
+    }
+}

+ 26 - 0
src/main/java/com/ssssssss/scripts/IfSqlNode.java

@@ -0,0 +1,26 @@
+package com.ssssssss.scripts;
+
+import com.ssssssss.context.RequestContext;
+
+import java.util.Objects;
+
+/**
+ * 对应XML中 <if>
+ */
+public class IfSqlNode extends SqlNode{
+
+    private String test;
+
+    public IfSqlNode(String test) {
+        this.test = test;
+    }
+
+    @Override
+    public String getSql(RequestContext context) {
+        Object value = context.evaluate(test);
+        if(Objects.equals(value,true)){
+            return executeChildren(context);
+        }
+        return "";
+    }
+}

+ 41 - 0
src/main/java/com/ssssssss/scripts/SqlNode.java

@@ -0,0 +1,41 @@
+package com.ssssssss.scripts;
+
+import com.ssssssss.context.RequestContext;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public abstract class SqlNode {
+
+    List<SqlNode> nodes = new ArrayList<>();
+
+    final Pattern expressionRegx = Pattern.compile("#\\{(.*?)\\}");
+
+    final Pattern replaceRegx = Pattern.compile("\\$\\{(.*?)\\}");
+
+    public void addChildNode(SqlNode node){
+        this.nodes.add(node);
+    }
+
+    public abstract String getSql(RequestContext context);
+
+    public String executeChildren(RequestContext context){
+        String sql = "";
+        for (SqlNode node : nodes) {
+            sql += StringUtils.defaultString(node.getSql(context)) + " ";
+        }
+        return sql;
+    }
+
+    public List<String> extractParameter(Pattern pattern,String sql) {
+        Matcher matcher = pattern.matcher(sql);
+        List<String> results = new ArrayList<>();
+        while (matcher.find()) {
+            results.add(matcher.group(1));
+        }
+        return results;
+    }
+}

+ 36 - 0
src/main/java/com/ssssssss/scripts/TextSqlNode.java

@@ -0,0 +1,36 @@
+package com.ssssssss.scripts;
+
+import com.ssssssss.context.RequestContext;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.List;
+import java.util.Objects;
+
+public class TextSqlNode extends SqlNode{
+
+    private String text;
+
+    public TextSqlNode(String text) {
+        this.text = text;
+    }
+
+    @Override
+    public String getSql(RequestContext context) {
+        String sql = text;
+        if(StringUtils.isNotBlank(text)){
+            List<String> expressions = extractParameter(expressionRegx,text);
+            for (String expression : expressions) {
+                Object val = context.evaluate(expression);
+                context.addParameter(val);
+                sql = sql.replaceFirst(expressionRegx.pattern(), "?");
+            }
+            expressions = extractParameter(replaceRegx,text);
+            for (String expression : expressions) {
+                Object val = context.evaluate(expression);
+                sql = sql.replaceFirst(replaceRegx.pattern(), Objects.toString(val,""));
+            }
+        }
+        return sql + executeChildren(context).trim();
+    }
+
+}

+ 100 - 0
src/main/java/com/ssssssss/session/Configuration.java

@@ -0,0 +1,100 @@
+package com.ssssssss.session;
+
+import com.ssssssss.utils.Assert;
+import com.ssssssss.utils.XmlFileLoader;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+public class Configuration implements InitializingBean {
+
+    private RequestMappingHandlerMapping requestMappingHandlerMapping;
+
+    private Object requestHandler;
+
+    private Method requestHandleMethod;
+
+    /**
+     * xml位置
+     */
+    private String xmlLocations;
+
+    /**
+     * 是否自动刷新
+     */
+    private boolean enableRefresh;
+
+    private Map<String,SqlStatement> statementMap = new ConcurrentHashMap<>();
+
+    private static Logger logger = LoggerFactory.getLogger(Configuration.class);
+
+    public SqlStatement getStatement(String requestMapping){
+        return statementMap.get(requestMapping);
+    }
+
+    /**
+     * 注册sql语句成接口,当已存在时,刷新其配置
+     */
+    public void addStatement(SqlStatement sqlStatement){
+        RequestMappingInfo requestMappingInfo = getRequestMappingInfo(sqlStatement);
+        if(statementMap.containsKey(sqlStatement.getRequestMapping())){
+            logger.debug("刷新接口:{}",sqlStatement.getRequestMapping());
+            requestMappingHandlerMapping.unregisterMapping(requestMappingInfo);
+        }else{
+            logger.debug("注册接口:{}",sqlStatement.getRequestMapping());
+        }
+        statementMap.put(sqlStatement.getRequestMapping(),sqlStatement);
+        requestMappingHandlerMapping.registerMapping(requestMappingInfo,requestHandler,requestHandleMethod);
+    }
+
+    private RequestMappingInfo getRequestMappingInfo(SqlStatement sqlStatement){
+        String requestMapping = sqlStatement.getRequestMapping();
+        Assert.isNotBlank(requestMapping,"request-mapping 不能为空!");
+        RequestMappingInfo.Builder builder = RequestMappingInfo.paths(requestMapping);
+        if(StringUtils.isNotBlank(sqlStatement.getRequestMethod())){
+            RequestMethod requestMethod = RequestMethod.valueOf(sqlStatement.getRequestMethod().toUpperCase());
+            Assert.isNotNull(requestMethod,String.format("不支持的请求方法:%s",sqlStatement.getRequestMethod()));
+            builder.methods(requestMethod);
+        }
+        return builder.build();
+    }
+
+    public void setRequestMappingHandlerMapping(RequestMappingHandlerMapping requestMappingHandlerMapping) {
+        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
+    }
+
+    public void setRequestHandler(Object requestHandler) {
+        this.requestHandler = requestHandler;
+    }
+
+    public void setRequestHandleMethod(Method requestHandleMethod) {
+        this.requestHandleMethod = requestHandleMethod;
+    }
+
+    public void setXmlLocations(String xmlLocations) {
+        this.xmlLocations = xmlLocations;
+    }
+
+    public void setEnableRefresh(boolean enableRefresh) {
+        this.enableRefresh = enableRefresh;
+    }
+
+    @Override
+    public void afterPropertiesSet() {
+        XmlFileLoader loader = new XmlFileLoader(xmlLocations, this);
+        loader.run();
+        if(enableRefresh){
+            Executors.newScheduledThreadPool(1).scheduleAtFixedRate(loader,3,3, TimeUnit.SECONDS);
+        }
+    }
+}

+ 77 - 0
src/main/java/com/ssssssss/session/SqlStatement.java

@@ -0,0 +1,77 @@
+package com.ssssssss.session;
+
+import com.ssssssss.enums.SqlMode;
+import com.ssssssss.scripts.SqlNode;
+
+public class SqlStatement {
+
+    private String requestMapping;
+
+    private String requestMethod;
+
+    private SqlMode sqlMode;
+
+    private SqlNode sqlNode;
+
+    private boolean pagination;
+
+    private Class<?> returnType;
+
+    private XMLStatement xmlStatement;
+
+    public String getRequestMapping() {
+        return requestMapping;
+    }
+
+    public void setRequestMapping(String requestMapping) {
+        this.requestMapping = requestMapping;
+    }
+
+    public String getRequestMethod() {
+        return requestMethod;
+    }
+
+    public void setRequestMethod(String requestMethod) {
+        this.requestMethod = requestMethod;
+    }
+
+    public SqlMode getSqlMode() {
+        return sqlMode;
+    }
+
+    public void setSqlMode(SqlMode sqlMode) {
+        this.sqlMode = sqlMode;
+    }
+
+    public SqlNode getSqlNode() {
+        return sqlNode;
+    }
+
+    public void setSqlNode(SqlNode sqlNode) {
+        this.sqlNode = sqlNode;
+    }
+
+    public XMLStatement getXmlStatement() {
+        return xmlStatement;
+    }
+
+    public void setXmlStatement(XMLStatement xmlStatement) {
+        this.xmlStatement = xmlStatement;
+    }
+
+    public Class<?> getReturnType() {
+        return returnType;
+    }
+
+    public void setReturnType(Class<?> returnType) {
+        this.returnType = returnType;
+    }
+
+    public boolean isPagination() {
+        return pagination;
+    }
+
+    public void setPagination(boolean pagination) {
+        this.pagination = pagination;
+    }
+}

+ 40 - 0
src/main/java/com/ssssssss/session/XMLStatement.java

@@ -0,0 +1,40 @@
+package com.ssssssss.session;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * xml文件对应的实体
+ */
+public class XMLStatement {
+
+    /**
+     * 映射URL路径
+     */
+    private String requestMapping;
+
+    /**
+     * xml文件中sql语句,包括select/insert/update/delete
+     */
+    private List<SqlStatement> sqlStatements = new ArrayList<>();
+
+    public String getRequestMapping() {
+        return requestMapping;
+    }
+
+    public void setRequestMapping(String requestMapping) {
+        this.requestMapping = requestMapping;
+    }
+
+    public List<SqlStatement> getSqlStatements() {
+        return sqlStatements;
+    }
+
+    public void setSqlStatements(List<SqlStatement> sqlStatements) {
+        this.sqlStatements = sqlStatements;
+    }
+
+    public void addSqlStatement(List<SqlStatement> sqlStatements){
+        this.sqlStatements.addAll(sqlStatements);
+    }
+}

+ 30 - 0
src/main/java/com/ssssssss/utils/Assert.java

@@ -0,0 +1,30 @@
+package com.ssssssss.utils;
+
+import com.ssssssss.exception.S8Exception;
+import org.apache.commons.lang3.StringUtils;
+
+public class Assert {
+
+    /**
+     * 断言值不能为空
+     * @param value
+     * @param message
+     */
+    public static void isNotNull(Object value,String message){
+        if(value == null){
+            throw new S8Exception(message);
+        }
+    }
+
+
+    /**
+     * 断言值不能为空字符串
+     * @param value
+     * @param message
+     */
+    public static void isNotBlank(String value,String message){
+        if(StringUtils.isBlank(value)){
+            throw new S8Exception(message);
+        }
+    }
+}

+ 165 - 0
src/main/java/com/ssssssss/utils/S8XMLFileParser.java

@@ -0,0 +1,165 @@
+package com.ssssssss.utils;
+
+import com.ssssssss.enums.SqlMode;
+import com.ssssssss.scripts.ForeachSqlNode;
+import com.ssssssss.scripts.IfSqlNode;
+import com.ssssssss.scripts.SqlNode;
+import com.ssssssss.scripts.TextSqlNode;
+import com.ssssssss.session.SqlStatement;
+import com.ssssssss.session.XMLStatement;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * xml文件解析
+ */
+public class S8XMLFileParser {
+
+    private static Logger logger = LoggerFactory.getLogger(S8XMLFileParser.class);
+
+    private static final List<String> TAG_NAMES = Arrays.asList("select", "insert", "update", "delete");
+
+    /**
+     * 解析xml文件
+     */
+    public static XMLStatement parse(File file) {
+        XMLStatement statement = null;
+        try {
+            Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
+            //解析根节点
+            statement = parseRoot(document);
+            // 解析select/insert/update/delete节点
+            for (String tagName : TAG_NAMES) {
+                statement.addSqlStatement(parseSqlStatement(statement, document.getElementsByTagName(tagName)));
+            }
+        } catch (SAXException | IOException | ParserConfigurationException e) {
+            logger.error("解析S8XML文件出错", e);
+        }
+        return statement;
+    }
+
+    /**
+     * 解析根节点
+     */
+    private static XMLStatement parseRoot(Document document) {
+        XMLStatement statement = new XMLStatement();
+        //解析请求路径
+        statement.setRequestMapping(document.getDocumentElement().getAttribute("request-mapping"));
+        return statement;
+    }
+
+    /**
+     * 解析节点
+     */
+    private static List<SqlStatement> parseSqlStatement(XMLStatement xmlStatement, NodeList nodeList) {
+        List<SqlStatement> sqlStatements = new ArrayList<>();
+        for (int i = 0, len = nodeList.getLength(); i < len; i++) {
+            Node item = nodeList.item(i);
+            SqlStatement sqlStatement = new SqlStatement();
+            sqlStatement.setXmlStatement(xmlStatement);
+            String requestMapping = getNodeAttributeValue(item, "request-mapping");
+            Assert.isNotBlank(requestMapping,"请求方法不能为空!");
+            // 设置请求路径
+            sqlStatement.setRequestMapping(StringUtils.defaultString(xmlStatement.getRequestMapping()) + requestMapping);
+            // 设置请求方法
+            sqlStatement.setRequestMethod(getNodeAttributeValue(item, "request-method"));
+            String returnType = getNodeAttributeValue(item, "return-type");
+            if("int".equalsIgnoreCase(returnType)){
+                sqlStatement.setReturnType(Integer.class);
+                sqlStatement.setSqlMode(SqlMode.SELECT_NUMBER);
+            }else if("double".equalsIgnoreCase(returnType)){
+                sqlStatement.setSqlMode(SqlMode.SELECT_NUMBER);
+                sqlStatement.setReturnType(Double.class);
+            }else if("long".equalsIgnoreCase(returnType)){
+                sqlStatement.setSqlMode(SqlMode.SELECT_NUMBER);
+                sqlStatement.setReturnType(Long.class);
+            }else if("string".equalsIgnoreCase(returnType)){
+                sqlStatement.setReturnType(String.class);
+            }else if("map".equalsIgnoreCase(returnType)){
+                sqlStatement.setSqlMode(SqlMode.SELECT_ONE);
+            }else{
+                sqlStatement.setSqlMode(SqlMode.SELECT_LIST);
+                //设置是否是分页
+                sqlStatement.setPagination("true".equalsIgnoreCase(getNodeAttributeValue(item,"page")));
+            }
+            SqlNode root = new TextSqlNode("");
+            // 解析sql语句
+            parseNodeList(root, item.getChildNodes());
+            sqlStatement.setSqlNode(root);
+            sqlStatements.add(sqlStatement);
+        }
+        return sqlStatements;
+    }
+
+    /**
+     * 递归解析子节点
+     */
+    private static void parseNodeList(SqlNode sqlNode, NodeList nodeList) {
+        for (int i = 0, len = nodeList.getLength(); i < len; i++) {
+            Node node = nodeList.item(i);
+            if (node.getNodeType() == Node.TEXT_NODE) {
+                sqlNode.addChildNode(new TextSqlNode(node.getNodeValue().trim()));
+            } else if(node.getNodeType() != Node.COMMENT_NODE){
+                String nodeName = node.getNodeName();
+                SqlNode childNode = null;
+                if ("foreach".equals(nodeName)) {
+                    childNode = parseForeachSqlNode(node);
+                } else if ("if".equals(nodeName)) {
+                    childNode = parseIfSqlNode(node);
+                } else {
+                    logger.error("不支持的标签:[{}]", nodeName);
+                    return;
+                }
+                sqlNode.addChildNode(childNode);
+                if (node.hasChildNodes()) {
+                    parseNodeList(childNode, node.getChildNodes());
+                }
+            }
+        }
+    }
+
+    /**
+     * 获取节点属性
+     *
+     * @param node         节点
+     * @param attributeKey 属性名
+     * @return 节点属性值,未设置时返回null
+     */
+    private static String getNodeAttributeValue(Node node, String attributeKey) {
+        Node item = node.getAttributes().getNamedItem(attributeKey);
+        return item != null ? item.getNodeValue() : null;
+    }
+
+    /**
+     * 解析foreach节点
+     */
+    private static ForeachSqlNode parseForeachSqlNode(Node node) {
+        ForeachSqlNode foreachSqlNode = new ForeachSqlNode();
+        foreachSqlNode.setCollection(getNodeAttributeValue(node, "collection"));
+        foreachSqlNode.setSeparator(getNodeAttributeValue(node, "separator"));
+        foreachSqlNode.setClose(getNodeAttributeValue(node, "close"));
+        foreachSqlNode.setOpen(getNodeAttributeValue(node, "open"));
+        foreachSqlNode.setItem(getNodeAttributeValue(node, "item"));
+        return foreachSqlNode;
+    }
+
+    /**
+     * 解析if节点
+     */
+    private static IfSqlNode parseIfSqlNode(Node node) {
+        return new IfSqlNode(getNodeAttributeValue(node, "test"));
+    }
+}

+ 51 - 0
src/main/java/com/ssssssss/utils/XmlFileLoader.java

@@ -0,0 +1,51 @@
+package com.ssssssss.utils;
+
+import com.ssssssss.session.Configuration;
+import com.ssssssss.session.XMLStatement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternResolver;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+public class XmlFileLoader implements Runnable{
+
+    private String pattern;
+
+    private Configuration configuration;
+
+    private static Logger logger = LoggerFactory.getLogger(XmlFileLoader.class);
+
+    private Map<String,Long> fileMap = new HashMap<>();
+
+    private ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
+
+    public XmlFileLoader(String pattern, Configuration configuration) {
+        this.pattern = pattern;
+        this.configuration = configuration;
+    }
+
+    @Override
+    public void run() {
+        try {
+            Resource[] resources = resourceResolver.getResources(this.pattern);
+            for (int i = 0; i < resources.length; i++) {
+                Resource resource = resources[i];
+                File file = resource.getFile();
+                Long lastModified = fileMap.get(resource.getDescription());
+                //判断是否更新
+                if(lastModified == null || lastModified < file.lastModified()){
+                    XMLStatement xmlStatement = S8XMLFileParser.parse(file);
+                    xmlStatement.getSqlStatements().forEach(configuration::addStatement);
+                }
+                fileMap.put(resource.getDescription(),file.lastModified());
+            }
+        } catch (Exception e) {
+            logger.error("读取失败",e);
+        }
+    }
+}

+ 2 - 2
src/main/resources/application.properties

@@ -1,8 +1,8 @@
 server.port=9999
 server.servlet.context-path=/ssssssss
+logging.level.com.ssssssss=debug
 
-
-spring.datasource.url=jdbc:mysql://localhost/ssssssss?useSSL=false&useUnicode=true&characterEncoding=UTF8
+spring.datasource.url=jdbc:mysql://localhost/test?useSSL=false&useUnicode=true&characterEncoding=UTF8
 spring.datasource.username=root
 spring.datasource.password=123456789
 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

+ 0 - 1
src/main/resources/ssssssss/role/list.sql

@@ -1 +0,0 @@
-select name,#{header.Host} host from sys_role where name = #{name} limit 8

+ 71 - 0
src/main/resources/ssssssss/role/test.xml

@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ssssssss request-mapping="/user" >
+    <!-- select/update/insert/delete -->
+    <select request-mapping="/list" request-method="get" page="true">
+        select name from sys_role where name in (
+        <foreach collection="names.split(',')" item="item" separator=",">
+            #{item}
+        </foreach>
+        )
+    </select>
+    <select request-mapping="/one" request-method="get" return-type="map">
+        select name from sys_role
+        <if test="name != null and name.length() > 0">
+            where name like concat('%','${name}','%')
+        </if>
+        limit 1
+    </select>
+    <select request-mapping="/test" page="true">
+        select
+        u.id,
+        u.name,
+        u.login_name,
+        u.unit_name,
+        u.user_type,
+        u.email,
+        u.phone,
+        u.mobile,
+        u.car_id,
+        u.USER_REGISTER_TYPE,
+        o.name office_name
+        from sys_user u
+        left join sys_office o on o.id = u.office_id
+        where u.del_flag = 0
+        <if test="officeId != null and officeId !='' and officeId != '0'.toString()">
+            and find_in_set(u.office_id,getOfficeChildList(#{officeId}))
+        </if>
+        <if test="name != null and name !=''">
+            and u.name like concat('%',#{name},'%')
+        </if>
+        <if test="unitName != null and unitName !=''">
+            and u.unit_name like concat('%',#{unitName},'%')
+        </if>
+        <if test="userRegisterType != null and userRegisterType !=''">
+            and u.user_register_type = #{userRegisterType}
+        </if>
+        <if test="loginName != null and loginName !=''">
+            and u.login_name like concat('%',#{loginName},'%')
+        </if>
+        <if test="carId != null and carId !=''">
+            and u.car_id like concat('%',#{carId},'%')
+        </if>
+        <if test="createBy != null and createBy !=''">
+            and u.create_by = #{createBy}
+        </if>
+        <if test="isRegisterFinish != null and isRegisterFinish != ''">
+            and u.is_register_finish = #{isRegisterFinish}
+        </if>
+        <if test="examineState != null and examineState != ''">
+            and u.EXAMINE_STATE = #{examineState}
+        </if>
+        <if test="roleIds != null and roleIds.length() > 0">
+            and u.id in (
+            select user_id from sys_user_role where role_id in
+            <foreach collection="roleIds.split(',')" item="roleId" open="(" separator="," close=")">
+                #{roleId}
+            </foreach>
+            )
+        </if>
+        order by u.create_date desc
+    </select>
+</ssssssss>

+ 0 - 1
src/main/resources/ssssssss/test/select.sql

@@ -1 +0,0 @@
-select name from sys_user [where id = #{id}] limit 10