diff --git a/src/main/java/org/smart4j/framework/aop/AopHelper.java b/src/main/java/org/smart4j/framework/aop/AopHelper.java index 6dd73b40952978c6c05eab6adec6b289d739491b..9945808deed1468184b2bac72702d3852ec1f0a0 100644 --- a/src/main/java/org/smart4j/framework/aop/AopHelper.java +++ b/src/main/java/org/smart4j/framework/aop/AopHelper.java @@ -143,7 +143,9 @@ public class AopHelper { if (StringUtil.isNotEmpty(pkg)) { if (StringUtil.isNotEmpty(cls)) { // 若类名不为空,则仅添加该类 - targetClassList.add(ClassUtil.loadClass(pkg + "." + cls, false)); + for(String clsName:cls.split(",")){ + targetClassList.add(ClassUtil.loadClass(pkg + "." + clsName, false)); + } } else { // 若注解不为空且不是 Aspect 注解,则添加指定包名下带有该注解的所有类 if (annotation != null && !annotation.equals(Aspect.class)) { diff --git a/src/main/java/org/smart4j/framework/dao/SqlHelper.java b/src/main/java/org/smart4j/framework/dao/SqlHelper.java index 843a53e50a951f8ee9a5f2a0f2a878cfc450cc3c..cc0476e693a13ec9eadba45c6c9d498d797ac100 100644 --- a/src/main/java/org/smart4j/framework/dao/SqlHelper.java +++ b/src/main/java/org/smart4j/framework/dao/SqlHelper.java @@ -139,6 +139,24 @@ public class SqlHelper { return sql.toString(); } + /** + * 生成 select 分页语句(数据库类型为:mysql、oracle、mssql) + */ + public static String generateSelectSqlForPager(int pageNumber, int pageSize, String sql) { + StringBuilder sqlsb = new StringBuilder(); + sqlsb.append(sql); + String dbType = DatabaseHelper.getDatabaseType(); + if (dbType.equalsIgnoreCase("mysql")) { + int pageStart = (pageNumber - 1) * pageSize; + appendSqlForMySql(sqlsb, pageStart, pageSize); + } else if (dbType.equalsIgnoreCase("oracle")) { + int pageStart = (pageNumber - 1) * pageSize + 1; + int pageEnd = pageStart + pageSize; + appendSqlForOracle(sqlsb, pageStart, pageEnd); + } + return sqlsb.toString(); + } + private static String getTable(Class entityClass) { return EntityHelper.getTableName(entityClass); } @@ -199,4 +217,21 @@ public class SqlHelper { sql.append(order); sql.append(") ").append(order); } + + private static void appendSqlForMySql(StringBuilder sql, int pageStart, int pageEnd) { + /* + select * from 表名 where 条件 order by 排序 limit 开始位置, 结束位置 + */ + sql.append(" limit ").append(pageStart).append(", ").append(pageEnd); + } + + private static void appendSqlForOracle(StringBuilder sql, int pageStart, int pageEnd) { + /* + select a.* from ( + select rownum rn, t.* from 表名 t where 条件 order by 排序 + ) a + where a.rn >= 开始位置 and a.rn < 结束位置 + */ + sql.append(") a where a.rn >= ").append(pageStart).append(" and a.rn < ").append(pageEnd); + } } diff --git a/src/main/java/org/smart4j/framework/ds/impl/AbstractDataSourceFactory.java b/src/main/java/org/smart4j/framework/ds/impl/AbstractDataSourceFactory.java index 8a36f7f26f7e7f5d1614e3bea26b4c6c77d6cd3b..38120c06e77ee25a124dfd0c160a08f1c9482202 100644 --- a/src/main/java/org/smart4j/framework/ds/impl/AbstractDataSourceFactory.java +++ b/src/main/java/org/smart4j/framework/ds/impl/AbstractDataSourceFactory.java @@ -1,7 +1,7 @@ package org.smart4j.framework.ds.impl; import javax.sql.DataSource; -import org.smart4j.framework.core.ConfigHelper; + import org.smart4j.framework.ds.DataSourceFactory; /** @@ -12,20 +12,20 @@ import org.smart4j.framework.ds.DataSourceFactory; */ public abstract class AbstractDataSourceFactory implements DataSourceFactory { - protected final String driver = ConfigHelper.getString("smart.framework.jdbc.driver"); + /*protected final String driver = ConfigHelper.getString("smart.framework.jdbc.driver"); protected final String url = ConfigHelper.getString("smart.framework.jdbc.url"); protected final String username = ConfigHelper.getString("smart.framework.jdbc.username"); - protected final String password = ConfigHelper.getString("smart.framework.jdbc.password"); + protected final String password = ConfigHelper.getString("smart.framework.jdbc.password");*/ @Override public final T getDataSource() { // 创建数据源对象 T ds = createDataSource(); // 设置基础属性 - setDriver(ds, driver); + /*setDriver(ds, driver); setUrl(ds, url); setUsername(ds, username); - setPassword(ds, password); + setPassword(ds, password);*/ // 设置高级属性 setAdvancedConfig(ds); return ds; diff --git a/src/main/java/org/smart4j/framework/mvc/ActionHelper.java b/src/main/java/org/smart4j/framework/mvc/ActionHelper.java index 7e885ecebb496d96ec72520c93682fd13ac2fcf2..4f1d74544d6b7439048bacc63bc52db8bf600d39 100644 --- a/src/main/java/org/smart4j/framework/mvc/ActionHelper.java +++ b/src/main/java/org/smart4j/framework/mvc/ActionHelper.java @@ -68,9 +68,9 @@ public class ActionHelper { private static void putActionMap(String requestMethod, String requestPath, Class actionClass, Method actionMethod, Map commonActionMap, Map regexpActionMap) { // 判断 Request Path 中是否带有占位符 - if (requestPath.matches(".+\\{\\w+\\}.*")) { + if (requestPath.matches(".+\\{[^/]+\\}.*")) { // 将请求路径中的占位符 {\w+} 转换为正则表达式 (\\w+) - requestPath = StringUtil.replaceAll(requestPath, "\\{\\w+\\}", "(\\\\w+)"); + requestPath = StringUtil.replaceAll(requestPath, "\\{[^/]+\\}", "([^/]+)"); // 将 Requester 与 Handler 放入 Regexp Action Map 中 regexpActionMap.put(new Requester(requestMethod, requestPath), new Handler(actionClass, actionMethod)); } else { diff --git a/src/main/java/org/smart4j/framework/mvc/DispatcherServlet.java b/src/main/java/org/smart4j/framework/mvc/DispatcherServlet.java index ff04bf4786e7f3bea38968ba49324913c6669617..1b2a3c2db95abb738d2a57c0170d4b1ee27c1967 100644 --- a/src/main/java/org/smart4j/framework/mvc/DispatcherServlet.java +++ b/src/main/java/org/smart4j/framework/mvc/DispatcherServlet.java @@ -1,6 +1,7 @@ package org.smart4j.framework.mvc; import java.io.IOException; + import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; @@ -8,6 +9,7 @@ import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.smart4j.framework.FrameworkConstant; @@ -44,13 +46,15 @@ public class DispatcherServlet extends HttpServlet { String currentRequestMethod = request.getMethod(); String currentRequestPath = WebUtil.getRequestPath(request); logger.debug("[Smart] {}:{}", currentRequestMethod, currentRequestPath); - // 将“/”请求重定向到首页 + // 当首页配置为非"/",将“/”请求重定向到首页 if (currentRequestPath.equals("/")) { - WebUtil.redirectRequest(FrameworkConstant.HOME_PAGE, request, response); - return; + if(!"/".equals(FrameworkConstant.HOME_PAGE)){ + WebUtil.redirectRequest(FrameworkConstant.HOME_PAGE, request, response); + return; + } } // 去掉当前请求路径末尾的“/” - if (currentRequestPath.endsWith("/")) { + if (!"/".equals(currentRequestPath)&¤tRequestPath.endsWith("/")) { currentRequestPath = currentRequestPath.substring(0, currentRequestPath.length() - 1); } // 获取 Handler diff --git a/src/main/java/org/smart4j/framework/mvc/UploadHelper.java b/src/main/java/org/smart4j/framework/mvc/UploadHelper.java index db75400ae0f7736e50c4103a5f11444ecd78459c..dfe3bcda278a5b517f4634cfaa7d4dc0c2be6e18 100644 --- a/src/main/java/org/smart4j/framework/mvc/UploadHelper.java +++ b/src/main/java/org/smart4j/framework/mvc/UploadHelper.java @@ -129,6 +129,26 @@ public class UploadHelper { } } + /** + * 上传文件 + */ + public static void uploadFile(String basePath, Multipart multipart,String fileName) { + try { + if (multipart != null) { + // 创建文件路径(绝对路径) + String filePath = basePath + fileName; + FileUtil.createFile(filePath); + // 执行流复制操作 + InputStream inputStream = new BufferedInputStream(multipart.getInputStream()); + OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(filePath)); + StreamUtil.copyStream(inputStream, outputStream); + } + } catch (Exception e) { + logger.error("上传文件出错!", e); + throw new RuntimeException(e); + } + } + /** * 批量上传文件 */ diff --git a/src/main/java/org/smart4j/framework/mvc/impl/DefaultHandlerInvoker.java b/src/main/java/org/smart4j/framework/mvc/impl/DefaultHandlerInvoker.java index ec3fdcc4a0678076268467f9fd53197c7431f337..48ba7c6167eff3431d525d60d67f43967fbe8d07 100644 --- a/src/main/java/org/smart4j/framework/mvc/impl/DefaultHandlerInvoker.java +++ b/src/main/java/org/smart4j/framework/mvc/impl/DefaultHandlerInvoker.java @@ -1,109 +1,127 @@ -package org.smart4j.framework.mvc.impl; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.smart4j.framework.InstanceFactory; -import org.smart4j.framework.ioc.BeanHelper; -import org.smart4j.framework.mvc.Handler; -import org.smart4j.framework.mvc.HandlerInvoker; -import org.smart4j.framework.mvc.UploadHelper; -import org.smart4j.framework.mvc.ViewResolver; -import org.smart4j.framework.mvc.bean.Params; -import org.smart4j.framework.util.CastUtil; -import org.smart4j.framework.util.ClassUtil; -import org.smart4j.framework.util.MapUtil; -import org.smart4j.framework.util.WebUtil; - -/** - * 默认 Handler 调用器 - * - * @author huangyong - * @since 2.3 - */ -public class DefaultHandlerInvoker implements HandlerInvoker { - - private ViewResolver viewResolver = InstanceFactory.getViewResolver(); - - @Override - public void invokeHandler(HttpServletRequest request, HttpServletResponse response, Handler handler) throws Exception { - // 获取 Action 相关信息 - Class actionClass = handler.getActionClass(); - Method actionMethod = handler.getActionMethod(); - // 从 BeanHelper 中创建 Action 实例 - Object actionInstance = BeanHelper.getBean(actionClass); - // 创建 Action 方法的参数列表 - List actionMethodParamList = createActionMethodParamList(request, handler); - // 检查参数列表是否合法 - checkParamList(actionMethod, actionMethodParamList); - // 调用 Action 方法 - Object actionMethodResult = invokeActionMethod(actionMethod, actionInstance, actionMethodParamList); - // 解析视图 - viewResolver.resolveView(request, response, actionMethodResult); - } - - public List createActionMethodParamList(HttpServletRequest request, Handler handler) throws Exception { - // 定义参数列表 - List paramList = new ArrayList(); - // 获取 Action 方法参数类型 - Class[] actionParamTypes = handler.getActionMethod().getParameterTypes(); - // 添加路径参数列表(请求路径中的带占位符参数) - paramList.addAll(createPathParamList(handler.getRequestPathMatcher(), actionParamTypes)); - // 分两种情况进行处理 - if (UploadHelper.isMultipart(request)) { - // 添加 Multipart 请求参数列表 - paramList.addAll(UploadHelper.createMultipartParamList(request)); - } else { - // 添加普通请求参数列表(包括 Query String 与 Form Data) - Map requestParamMap = WebUtil.getRequestParamMap(request); - if (MapUtil.isNotEmpty(requestParamMap)) { - paramList.add(new Params(requestParamMap)); - } - } - // 返回参数列表 - return paramList; - } - - private List createPathParamList(Matcher requestPathMatcher, Class[] actionParamTypes) { - // 定义参数列表 - List paramList = new ArrayList(); - // 遍历正则表达式中所匹配的组 - for (int i = 1; i <= requestPathMatcher.groupCount(); i++) { - // 获取请求参数 - String param = requestPathMatcher.group(i); - // 获取参数类型(支持四种类型:int/Integer、long/Long、double/Double、String) - Class paramType = actionParamTypes[i - 1]; - if (ClassUtil.isInt(paramType)) { - paramList.add(CastUtil.castInt(param)); - } else if (ClassUtil.isLong(paramType)) { - paramList.add(CastUtil.castLong(param)); - } else if (ClassUtil.isDouble(paramType)) { - paramList.add(CastUtil.castDouble(param)); - } else if (ClassUtil.isString(paramType)) { - paramList.add(param); - } - } - // 返回参数列表 - return paramList; - } - - private Object invokeActionMethod(Method actionMethod, Object actionInstance, List actionMethodParamList) throws IllegalAccessException, InvocationTargetException { - // 通过反射调用 Action 方法 - actionMethod.setAccessible(true); // 取消类型安全检测(可提高反射性能) - return actionMethod.invoke(actionInstance, actionMethodParamList.toArray()); - } - - private void checkParamList(Method actionMethod, List actionMethodParamList) { - // 判断 Action 方法参数的个数是否匹配 - Class[] actionMethodParameterTypes = actionMethod.getParameterTypes(); - if (actionMethodParameterTypes.length != actionMethodParamList.size()) { - String message = String.format("因为参数个数不匹配,所以无法调用 Action 方法!原始参数个数:%d,实际参数个数:%d", actionMethodParameterTypes.length, actionMethodParamList.size()); - throw new RuntimeException(message); - } - } -} +package org.smart4j.framework.mvc.impl; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.smart4j.framework.InstanceFactory; +import org.smart4j.framework.ioc.BeanHelper; +import org.smart4j.framework.mvc.Handler; +import org.smart4j.framework.mvc.HandlerInvoker; +import org.smart4j.framework.mvc.UploadHelper; +import org.smart4j.framework.mvc.ViewResolver; +import org.smart4j.framework.mvc.bean.Params; +import org.smart4j.framework.util.CastUtil; +import org.smart4j.framework.util.ClassUtil; +import org.smart4j.framework.util.MapUtil; +import org.smart4j.framework.util.WebUtil; + +/** + * 默认 Handler 调用器 + * + * @author huangyong + * @since 2.3 + */ +public class DefaultHandlerInvoker implements HandlerInvoker { + + private ViewResolver viewResolver = InstanceFactory.getViewResolver(); + + @Override + public void invokeHandler(HttpServletRequest request, HttpServletResponse response, Handler handler) throws Exception { + // 获取 Action 相关信息 + Class actionClass = handler.getActionClass(); + Method actionMethod = handler.getActionMethod(); + // 从 BeanHelper 中创建 Action 实例 + Object actionInstance = BeanHelper.getBean(actionClass); + // 创建 Action 方法的参数列表 + List actionMethodParamList = createActionMethodParamList(request, handler); + // 检查参数列表是否合法 + //checkParamList(actionMethod, actionMethodParamList); + // 调整参数 + adaptParamList(actionMethod, actionMethodParamList); + // 调用 Action 方法 + Object actionMethodResult = invokeActionMethod(actionMethod, actionInstance, actionMethodParamList); + // 解析视图 + viewResolver.resolveView(request, response, actionMethodResult); + } + + public List createActionMethodParamList(HttpServletRequest request, Handler handler) throws Exception { + // 定义参数列表 + List paramList = new ArrayList(); + // 获取 Action 方法参数类型 + Class[] actionParamTypes = handler.getActionMethod().getParameterTypes(); + // 添加路径参数列表(请求路径中的带占位符参数) + paramList.addAll(createPathParamList(handler.getRequestPathMatcher(), actionParamTypes)); + // 分两种情况进行处理 + if (UploadHelper.isMultipart(request)) { + // 添加 Multipart 请求参数列表 + paramList.addAll(UploadHelper.createMultipartParamList(request)); + } else { + // 添加普通请求参数列表(包括 Query String 与 Form Data) + Map requestParamMap = WebUtil.getRequestParamMap(request); + if (MapUtil.isNotEmpty(requestParamMap)) { + paramList.add(new Params(requestParamMap)); + } + } + // 返回参数列表 + return paramList; + } + + private List createPathParamList(Matcher requestPathMatcher, Class[] actionParamTypes) { + // 定义参数列表 + List paramList = new ArrayList(); + // 遍历正则表达式中所匹配的组 + for (int i = 1; i <= requestPathMatcher.groupCount(); i++) { + // 获取请求参数 + String param = requestPathMatcher.group(i); + // 获取参数类型(支持四种类型:int/Integer、long/Long、double/Double、String) + Class paramType = actionParamTypes[i - 1]; + if (ClassUtil.isInt(paramType)) { + paramList.add(CastUtil.castInt(param)); + } else if (ClassUtil.isLong(paramType)) { + paramList.add(CastUtil.castLong(param)); + } else if (ClassUtil.isDouble(paramType)) { + paramList.add(CastUtil.castDouble(param)); + } else if (ClassUtil.isString(paramType)) { + paramList.add(param); + } + } + // 返回参数列表 + return paramList; + } + + private Object invokeActionMethod(Method actionMethod, Object actionInstance, List actionMethodParamList) throws IllegalAccessException, InvocationTargetException { + // 通过反射调用 Action 方法 + actionMethod.setAccessible(true); // 取消类型安全检测(可提高反射性能) + return actionMethod.invoke(actionInstance, actionMethodParamList.toArray()); + } + + private void checkParamList(Method actionMethod, List actionMethodParamList) { + // 判断 Action 方法参数的个数是否匹配 + Class[] actionMethodParameterTypes = actionMethod.getParameterTypes(); + if (actionMethodParameterTypes.length != actionMethodParamList.size()) { + String message = String.format("因为参数个数不匹配,所以无法调用 Action 方法!原始参数个数:%d,实际参数个数:%d", actionMethodParameterTypes.length, actionMethodParamList.size()); + throw new RuntimeException(message); + } + } + + private void adaptParamList(Method actionMethod, List actionMethodParamList) { + // 判断 Action 方法参数的个数是否匹配 + Class[] actionMethodParameterTypes = actionMethod.getParameterTypes(); + int dmp=actionMethodParameterTypes.length; + int rmp=actionMethodParamList.size(); + if (dmp > rmp){ + for(int i=0;i List selectListForPager(int pageNumber, int pageSize, Class entityClass, String qsql, Object... params) { + String sql = SqlHelper.generateSelectSqlForPager(pageNumber, pageSize, qsql); + return DatabaseHelper.queryEntityList(entityClass, sql, params); + } + /** * 查询多条数据,并转为映射 */ diff --git a/src/main/java/org/smart4j/framework/util/WebUtil.java b/src/main/java/org/smart4j/framework/util/WebUtil.java index 25a26ea9daec1885d2a86090e2eef7f7070f85bf..5ef97eaa0bf0aa0b7059ceeb0ff4685ff04326c5 100644 --- a/src/main/java/org/smart4j/framework/util/WebUtil.java +++ b/src/main/java/org/smart4j/framework/util/WebUtil.java @@ -1,318 +1,332 @@ -package org.smart4j.framework.util; - -import java.awt.Color; -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.FileInputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.util.Enumeration; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Random; -import javax.imageio.ImageIO; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.apache.commons.io.FilenameUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.smart4j.framework.FrameworkConstant; - -/** - * Web 操作工具类 - * - * @author huangyong - * @since 1.0 - */ -public class WebUtil { - - private static final Logger logger = LoggerFactory.getLogger(WebUtil.class); - - /** - * 将数据以 JSON 格式写入响应中 - */ - public static void writeJSON(HttpServletResponse response, Object data) { - try { - // 设置响应头 - response.setContentType("application/json"); // 指定内容类型为 JSON 格式 - response.setCharacterEncoding(FrameworkConstant.UTF_8); // 防止中文乱码 - // 向响应中写入数据 - PrintWriter writer = response.getWriter(); - writer.write(JsonUtil.toJSON(data)); // 转为 JSON 字符串 - writer.flush(); - writer.close(); - } catch (Exception e) { - logger.error("在响应中写数据出错!", e); - throw new RuntimeException(e); - } - } - - /** - * 将数据以 HTML 格式写入响应中(在 JS 中获取的是 JSON 字符串,而不是 JSON 对象) - */ - public static void writeHTML(HttpServletResponse response, Object data) { - try { - // 设置响应头 - response.setContentType("text/html"); // 指定内容类型为 HTML 格式 - response.setCharacterEncoding(FrameworkConstant.UTF_8); // 防止中文乱码 - // 向响应中写入数据 - PrintWriter writer = response.getWriter(); - writer.write(JsonUtil.toJSON(data)); // 转为 JSON 字符串 - writer.flush(); - writer.close(); - } catch (Exception e) { - logger.error("在响应中写数据出错!", e); - throw new RuntimeException(e); - } - } - - /** - * 从请求中获取所有参数(当参数名重复时,用后者覆盖前者) - */ - public static Map getRequestParamMap(HttpServletRequest request) { - Map paramMap = new LinkedHashMap(); - try { - String method = request.getMethod(); - if (method.equalsIgnoreCase("put") || method.equalsIgnoreCase("delete")) { - String queryString = CodecUtil.decodeURL(StreamUtil.getString(request.getInputStream())); - if (StringUtil.isNotEmpty(queryString)) { - String[] qsArray = StringUtil.splitString(queryString, "&"); - if (ArrayUtil.isNotEmpty(qsArray)) { - for (String qs : qsArray) { - String[] array = StringUtil.splitString(qs, "="); - if (ArrayUtil.isNotEmpty(array) && array.length == 2) { - String paramName = array[0]; - String paramValue = array[1]; - if (checkParamName(paramName)) { - if (paramMap.containsKey(paramName)) { - paramValue = paramMap.get(paramName) + StringUtil.SEPARATOR + paramValue; - } - paramMap.put(paramName, paramValue); - } - } - } - } - } - } else { - Enumeration paramNames = request.getParameterNames(); - while (paramNames.hasMoreElements()) { - String paramName = paramNames.nextElement(); - if (checkParamName(paramName)) { - String[] paramValues = request.getParameterValues(paramName); - if (ArrayUtil.isNotEmpty(paramValues)) { - if (paramValues.length == 1) { - paramMap.put(paramName, paramValues[0]); - } else { - StringBuilder paramValue = new StringBuilder(""); - for (int i = 0; i < paramValues.length; i++) { - paramValue.append(paramValues[i]); - if (i != paramValues.length - 1) { - paramValue.append(StringUtil.SEPARATOR); - } - } - paramMap.put(paramName, paramValue.toString()); - } - } - } - } - } - } catch (Exception e) { - logger.error("获取请求参数出错!", e); - throw new RuntimeException(e); - } - return paramMap; - } - - private static boolean checkParamName(String paramName) { - return !paramName.equals("_"); // 忽略 jQuery 缓存参数 - } - - /** - * 转发请求 - */ - public static void forwardRequest(String path, HttpServletRequest request, HttpServletResponse response) { - try { - request.getRequestDispatcher(path).forward(request, response); - } catch (Exception e) { - logger.error("转发请求出错!", e); - throw new RuntimeException(e); - } - } - - /** - * 重定向请求 - */ - public static void redirectRequest(String path, HttpServletRequest request, HttpServletResponse response) { - try { - response.sendRedirect(request.getContextPath() + path); - } catch (Exception e) { - logger.error("重定向请求出错!", e); - throw new RuntimeException(e); - } - } - - /** - * 发送错误代码 - */ - public static void sendError(int code, String message, HttpServletResponse response) { - try { - response.sendError(code, message); - } catch (Exception e) { - logger.error("发送错误代码出错!", e); - throw new RuntimeException(e); - } - } - - /** - * 判断是否为 AJAX 请求 - */ - public static boolean isAJAX(HttpServletRequest request) { - return request.getHeader("X-Requested-With") != null; - } - - /** - * 获取请求路径 - */ - public static String getRequestPath(HttpServletRequest request) { - String servletPath = request.getServletPath(); - String pathInfo = StringUtil.defaultIfEmpty(request.getPathInfo(), ""); - return servletPath + pathInfo; - } - - /** - * 从 Cookie 中获取数据 - */ - public static String getCookie(HttpServletRequest request, String name) { - String value = ""; - try { - Cookie[] cookieArray = request.getCookies(); - if (cookieArray != null) { - for (Cookie cookie : cookieArray) { - if (StringUtil.isNotEmpty(name) && name.equals(cookie.getName())) { - value = CodecUtil.decodeURL(cookie.getValue()); - break; - } - } - } - } catch (Exception e) { - logger.error("获取 Cookie 出错!", e); - throw new RuntimeException(e); - } - return value; - } - - /** - * 下载文件 - */ - public static void downloadFile(HttpServletResponse response, String filePath) { - try { - String originalFileName = FilenameUtils.getName(filePath); - String downloadedFileName = new String(originalFileName.getBytes("GBK"), "ISO8859_1"); // 防止中文乱码 - - response.setContentType("application/octet-stream"); - response.addHeader("Content-Disposition", "attachment;filename=\"" + downloadedFileName + "\""); - - InputStream inputStream = new BufferedInputStream(new FileInputStream(filePath)); - OutputStream outputStream = new BufferedOutputStream(response.getOutputStream()); - StreamUtil.copyStream(inputStream, outputStream); - } catch (Exception e) { - logger.error("下载文件出错!", e); - throw new RuntimeException(e); - } - } - - /** - * 设置 Redirect URL 到 Session 中 - */ - public static void setRedirectUrl(HttpServletRequest request, String sessionKey) { - if (!isAJAX(request)) { - String requestPath = getRequestPath(request); - request.getSession().setAttribute(sessionKey, requestPath); - } - } - - /** - * 创建验证码 - */ - public static String createCaptcha(HttpServletResponse response) { - StringBuilder captcha = new StringBuilder(); - try { - // 参数初始化 - int width = 60; // 验证码图片的宽度 - int height = 25; // 验证码图片的高度 - int codeCount = 4; // 验证码字符个数 - int codeX = width / (codeCount + 1); // 字符横向间距 - int codeY = height - 4; // 字符纵向间距 - int fontHeight = height - 2; // 字体高度 - int randomSeed = 10; // 随机数种子 - char[] codeSequence = { // 验证码中可出现的字符 - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' - }; - // 创建图像 - BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); - Graphics2D g = bi.createGraphics(); - // 将图像填充为白色 - g.setColor(Color.WHITE); - g.fillRect(0, 0, width, height); - // 设置字体 - g.setFont(new Font("Courier New", Font.BOLD, fontHeight)); - // 绘制边框 - g.setColor(Color.BLACK); - g.drawRect(0, 0, width - 1, height - 1); - // 产生随机干扰线(160条) - g.setColor(Color.WHITE); - // 创建随机数生成器 - Random random = new Random(); - for (int i = 0; i < 160; i++) { - int x = random.nextInt(width); - int y = random.nextInt(height); - int xl = random.nextInt(12); - int yl = random.nextInt(12); - g.drawLine(x, y, x + xl, y + yl); - } - // 生成随机验证码 - int red, green, blue; - for (int i = 0; i < codeCount; i++) { - // 获取随机验证码 - String validateCode = String.valueOf(codeSequence[random.nextInt(randomSeed)]); - // 随机构造颜色值 - red = random.nextInt(255); - green = random.nextInt(255); - blue = random.nextInt(255); - // 将带有颜色的验证码绘制到图像中 - g.setColor(new Color(red, green, blue)); - g.drawString(validateCode, (i + 1) * codeX - 6, codeY); - // 将产生的随机数拼接起来 - captcha.append(validateCode); - } - // 禁止图像缓存 - response.setHeader("Cache-Control", "no-store"); - response.setHeader("Pragma", "no-cache"); - response.setDateHeader("Expires", 0); - // 设置响应类型为 JPEG 图片 - response.setContentType("image/jpeg"); - // 将缓冲图像写到 Servlet 输出流中 - ServletOutputStream sos = response.getOutputStream(); - ImageIO.write(bi, "jpeg", sos); - sos.close(); - } catch (Exception e) { - logger.error("创建验证码出错!", e); - throw new RuntimeException(e); - } - return captcha.toString(); - } - - /** - * 是否为 IE 浏览器 - */ - public boolean isIE(HttpServletRequest request) { - String agent = request.getHeader("User-Agent"); - return agent != null && agent.contains("MSIE"); - } -} +package org.smart4j.framework.util; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Enumeration; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.imageio.ImageIO; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.smart4j.framework.FrameworkConstant; + +/** + * Web 操作工具类 + * + * @author huangyong + * @since 1.0 + */ +public class WebUtil { + + private static final Logger logger = LoggerFactory.getLogger(WebUtil.class); + + /** + * 将数据以 JSON 格式写入响应中 + */ + public static void writeJSON(HttpServletResponse response, Object data) { + try { + // 设置响应头 + response.setContentType("application/json"); // 指定内容类型为 JSON 格式 + response.setCharacterEncoding(FrameworkConstant.UTF_8); // 防止中文乱码 + // 向响应中写入数据 + PrintWriter writer = response.getWriter(); + writer.write(JsonUtil.toJSON(data)); // 转为 JSON 字符串 + writer.flush(); + writer.close(); + } catch (Exception e) { + logger.error("在响应中写数据出错!", e); + throw new RuntimeException(e); + } + } + + /** + * 将数据以 HTML 格式写入响应中(在 JS 中获取的是 JSON 字符串,而不是 JSON 对象) + */ + public static void writeHTML(HttpServletResponse response, Object data) { + try { + // 设置响应头 + response.setContentType("text/html"); // 指定内容类型为 HTML 格式 + response.setCharacterEncoding(FrameworkConstant.UTF_8); // 防止中文乱码 + // 向响应中写入数据 + PrintWriter writer = response.getWriter(); + writer.write(JsonUtil.toJSON(data)); // 转为 JSON 字符串 + writer.flush(); + writer.close(); + } catch (Exception e) { + logger.error("在响应中写数据出错!", e); + throw new RuntimeException(e); + } + } + + /** + * 从请求中获取所有参数(当参数名重复时,用后者覆盖前者) + */ + public static Map getRequestParamMap(HttpServletRequest request) { + Map paramMap = new LinkedHashMap(); + try { + String method = request.getMethod(); + if (method.equalsIgnoreCase("put") || method.equalsIgnoreCase("delete")) { + //修正put 传参的值带有&符号是不能正确解析问题 + String queryStringEncode=StreamUtil.getString(request.getInputStream()); + // 解析参数正则 + Pattern p = Pattern.compile("&?(.*?)=(.*?)(?=&.+=)|&?(.+)=(.*)$"); + Matcher m = p.matcher(queryStringEncode); + while(m.find()){ + String paramName=null; + String paramValue=null; + String march1=StringUtils.isEmpty(m.group(1))?"":CodecUtil.decodeURL(m.group(1)); + String march2=StringUtils.isEmpty(m.group(3))?"":CodecUtil.decodeURL(m.group(3)); + if(StringUtils.isNotEmpty(march1)){//非最后一个参数 + + paramName=CodecUtil.decodeURL(m.group(1)); + paramValue = CodecUtil.decodeURL(m.group(2)); + }else if(StringUtils.isNotEmpty(march2)){//最后一个参数 + + paramName=CodecUtil.decodeURL(m.group(3)); + paramValue = CodecUtil.decodeURL(m.group(4)); + } + if(StringUtils.isNotEmpty(paramName)){ + if (checkParamName(paramName)) { + if (paramMap.containsKey(paramName)) { + paramValue = paramMap.get(paramName) + StringUtil.SEPARATOR + paramValue; + } + paramMap.put(paramName, paramValue); + } + } + } + } else { + Enumeration paramNames = request.getParameterNames(); + while (paramNames.hasMoreElements()) { + String paramName = paramNames.nextElement(); + if (checkParamName(paramName)) { + String[] paramValues = request.getParameterValues(paramName); + if (ArrayUtil.isNotEmpty(paramValues)) { + if (paramValues.length == 1) { + paramMap.put(paramName, paramValues[0]); + } else { + StringBuilder paramValue = new StringBuilder(""); + for (int i = 0; i < paramValues.length; i++) { + paramValue.append(paramValues[i]); + if (i != paramValues.length - 1) { + paramValue.append(StringUtil.SEPARATOR); + } + } + paramMap.put(paramName, paramValue.toString()); + } + } + } + } + } + } catch (Exception e) { + logger.error("获取请求参数出错!", e); + throw new RuntimeException(e); + } + return paramMap; + } + + private static boolean checkParamName(String paramName) { + return !paramName.equals("_"); // 忽略 jQuery 缓存参数 + } + + /** + * 转发请求 + */ + public static void forwardRequest(String path, HttpServletRequest request, HttpServletResponse response) { + try { + request.getRequestDispatcher(path).forward(request, response); + } catch (Exception e) { + logger.error("转发请求出错!", e); + throw new RuntimeException(e); + } + } + + /** + * 重定向请求 + */ + public static void redirectRequest(String path, HttpServletRequest request, HttpServletResponse response) { + try { + response.sendRedirect(request.getContextPath() + path); + } catch (Exception e) { + logger.error("重定向请求出错!", e); + throw new RuntimeException(e); + } + } + + /** + * 发送错误代码 + */ + public static void sendError(int code, String message, HttpServletResponse response) { + try { + response.sendError(code, message); + } catch (Exception e) { + logger.error("发送错误代码出错!", e); + throw new RuntimeException(e); + } + } + + /** + * 判断是否为 AJAX 请求 + */ + public static boolean isAJAX(HttpServletRequest request) { + return request.getHeader("X-Requested-With") != null; + } + + /** + * 获取请求路径 + */ + public static String getRequestPath(HttpServletRequest request) { + String servletPath = request.getServletPath(); + String pathInfo = StringUtil.defaultIfEmpty(request.getPathInfo(), ""); + return servletPath + pathInfo; + } + + /** + * 从 Cookie 中获取数据 + */ + public static String getCookie(HttpServletRequest request, String name) { + String value = ""; + try { + Cookie[] cookieArray = request.getCookies(); + if (cookieArray != null) { + for (Cookie cookie : cookieArray) { + if (StringUtil.isNotEmpty(name) && name.equals(cookie.getName())) { + value = CodecUtil.decodeURL(cookie.getValue()); + break; + } + } + } + } catch (Exception e) { + logger.error("获取 Cookie 出错!", e); + throw new RuntimeException(e); + } + return value; + } + + /** + * 下载文件 + */ + public static void downloadFile(HttpServletResponse response, String filePath) { + try { + String originalFileName = FilenameUtils.getName(filePath); + String downloadedFileName = new String(originalFileName.getBytes("GBK"), "ISO8859_1"); // 防止中文乱码 + + response.setContentType("application/octet-stream"); + response.addHeader("Content-Disposition", "attachment;filename=\"" + downloadedFileName + "\""); + + InputStream inputStream = new BufferedInputStream(new FileInputStream(filePath)); + OutputStream outputStream = new BufferedOutputStream(response.getOutputStream()); + StreamUtil.copyStream(inputStream, outputStream); + } catch (Exception e) { + logger.error("下载文件出错!", e); + throw new RuntimeException(e); + } + } + + /** + * 设置 Redirect URL 到 Session 中 + */ + public static void setRedirectUrl(HttpServletRequest request, String sessionKey) { + if (!isAJAX(request)) { + String requestPath = getRequestPath(request); + request.getSession().setAttribute(sessionKey, requestPath); + } + } + + /** + * 创建验证码 + */ + public static String createCaptcha(HttpServletResponse response) { + StringBuilder captcha = new StringBuilder(); + try { + // 参数初始化 + int width = 60; // 验证码图片的宽度 + int height = 25; // 验证码图片的高度 + int codeCount = 4; // 验证码字符个数 + int codeX = width / (codeCount + 1); // 字符横向间距 + int codeY = height - 4; // 字符纵向间距 + int fontHeight = height - 2; // 字体高度 + int randomSeed = 10; // 随机数种子 + char[] codeSequence = { // 验证码中可出现的字符 + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' + }; + // 创建图像 + BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics2D g = bi.createGraphics(); + // 将图像填充为白色 + g.setColor(Color.WHITE); + g.fillRect(0, 0, width, height); + // 设置字体 + g.setFont(new Font("Courier New", Font.BOLD, fontHeight)); + // 绘制边框 + g.setColor(Color.BLACK); + g.drawRect(0, 0, width - 1, height - 1); + // 产生随机干扰线(160条) + g.setColor(Color.WHITE); + // 创建随机数生成器 + Random random = new Random(); + for (int i = 0; i < 160; i++) { + int x = random.nextInt(width); + int y = random.nextInt(height); + int xl = random.nextInt(12); + int yl = random.nextInt(12); + g.drawLine(x, y, x + xl, y + yl); + } + // 生成随机验证码 + int red, green, blue; + for (int i = 0; i < codeCount; i++) { + // 获取随机验证码 + String validateCode = String.valueOf(codeSequence[random.nextInt(randomSeed)]); + // 随机构造颜色值 + red = random.nextInt(255); + green = random.nextInt(255); + blue = random.nextInt(255); + // 将带有颜色的验证码绘制到图像中 + g.setColor(new Color(red, green, blue)); + g.drawString(validateCode, (i + 1) * codeX - 6, codeY); + // 将产生的随机数拼接起来 + captcha.append(validateCode); + } + // 禁止图像缓存 + response.setHeader("Cache-Control", "no-store"); + response.setHeader("Pragma", "no-cache"); + response.setDateHeader("Expires", 0); + // 设置响应类型为 JPEG 图片 + response.setContentType("image/jpeg"); + // 将缓冲图像写到 Servlet 输出流中 + ServletOutputStream sos = response.getOutputStream(); + ImageIO.write(bi, "jpeg", sos); + sos.close(); + } catch (Exception e) { + logger.error("创建验证码出错!", e); + throw new RuntimeException(e); + } + return captcha.toString(); + } + + /** + * 是否为 IE 浏览器 + */ + public boolean isIE(HttpServletRequest request) { + String agent = request.getHeader("User-Agent"); + return agent != null && agent.contains("MSIE"); + } +}