参数类型必须为 FileInfo 或 {@code List
上行数据中参数名应与本注解的 name 一致, 默认值为 data
11 | *上行数据可是 JSON 格式或 com.google.gson.JsonPrimitive ( Integer, Long, Short, Float, Double, Byte, Boolean, Character )
12 | * @see com.google.gson.JsonPrimitive 13 | */ 14 | @Target(ElementType.PARAMETER) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface Param { 17 | /** 18 | * 参数名 19 | * @return 参数名 20 | */ 21 | String name() default "data"; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/bailey/web/lighter/utils/GsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.bailey.web.lighter.utils; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | 6 | import java.sql.Timestamp; 7 | import java.util.Date; 8 | 9 | /** 10 | * Gson 管理工具类 11 | */ 12 | public class GsonUtil { 13 | public static Gson getGsonInstance() { 14 | GsonBuilder gsonBuilder = new GsonBuilder(); 15 | GsonUTCDateAdapter gsonUTCDateAdapter = new GsonUTCDateAdapter(); 16 | gsonBuilder.registerTypeAdapter(Date.class, gsonUTCDateAdapter); 17 | gsonBuilder.registerTypeAdapter(java.sql.Date.class, gsonUTCDateAdapter); 18 | gsonBuilder.registerTypeAdapter(Timestamp.class, gsonUTCDateAdapter); 19 | return gsonBuilder.create(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/bailey/web/lighter/vo/ListWithTotal.java: -------------------------------------------------------------------------------- 1 | package com.bailey.web.lighter.vo; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author Bailey 7 | */ 8 | public class ListWithTotal规则中的星号("*")表示此部分使用UUID替换, 例如: "tmp*" 表示使用 "tmp" + 32位UUID 作为文件名
23 | *文件扩展名始终与原文件一致
24 | * @return 服务器端文件命名规则 25 | */ 26 | String nameRule() default "*"; 27 | 28 | /** 29 | * 单个文件的最大字节数 30 | * @return 单个文件的最大字节数 31 | */ 32 | int maxFileSize() default 1024 * 1024 * 40; 33 | 34 | /** 35 | * 请求的最大字节数 36 | * @return 请求的最大字节数 37 | */ 38 | int maxRequestSize() default 1024 * 1024 * 50; 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 baileykm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/com/bailey/web/lighter/action/ActionSupport.java: -------------------------------------------------------------------------------- 1 | package com.bailey.web.lighter.action; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import javax.servlet.http.HttpServletResponse; 5 | import javax.servlet.http.HttpSession; 6 | 7 | /** 8 | * Action 的公共父类, 所示Action应继承此类 9 | * 10 | * @author Bailey 11 | */ 12 | public abstract class ActionSupport { 13 | 14 | private HttpServletRequest request; 15 | private HttpServletResponse response; 16 | 17 | void setRequest(HttpServletRequest request) { 18 | this.request = request; 19 | } 20 | 21 | void setResponse(HttpServletResponse response) { 22 | this.response = response; 23 | } 24 | 25 | /** 26 | * 获得Request对象 27 | * 28 | * @return Request 29 | */ 30 | protected HttpServletRequest getRequest() { 31 | return request; 32 | } 33 | 34 | /** 35 | * 获得Response对象 36 | * 37 | * @return Response 38 | */ 39 | protected HttpServletResponse getResponse() { 40 | return response; 41 | } 42 | 43 | 44 | /** 45 | * 获得Session对象 46 | * 47 | * @return Session 48 | */ 49 | protected HttpSession getSession() { 50 | return request.getSession(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/bailey/web/lighter/ContainerListener.java: -------------------------------------------------------------------------------- 1 | package com.bailey.web.lighter; 2 | 3 | import com.bailey.web.lighter.action.ActionHelper; 4 | import com.bailey.web.lighter.servlet.DispatcherServlet; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import javax.servlet.ServletContext; 8 | import javax.servlet.ServletContextEvent; 9 | import javax.servlet.ServletContextListener; 10 | import javax.servlet.annotation.WebListener; 11 | 12 | /** 13 | * 监听Web容器初始化事件, 进行初始化 14 | * 15 | * @author Bailey 16 | */ 17 | @WebListener 18 | public class ContainerListener implements ServletContextListener { 19 | 20 | @Override 21 | public void contextInitialized(ServletContextEvent sce) { 22 | // 加载配置 23 | WebLighterConfig.loadConfiguration(); 24 | 25 | // 初始化 ActionHelper 26 | try { 27 | ActionHelper.initRequestHandlers(); 28 | } catch (Exception e) { 29 | LoggerFactory.getLogger(WebLighterConfig.LIB_NAME).error("Web-lighter initialization exception!", e); 30 | } 31 | 32 | ServletContext context = sce.getServletContext(); 33 | context.addServlet("wlqDispatcher", DispatcherServlet.class).addMapping(WebLighterConfig.getUrlPrefix() + "/*"); 34 | } 35 | 36 | @Override 37 | public void contextDestroyed(ServletContextEvent sce) { 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/java/com/bailey/web/lighter/annotation/Request.java: -------------------------------------------------------------------------------- 1 | package com.bailey.web.lighter.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * 标注于Action中的方法上, 说明该方法为处理前端请求的方法. 10 | *参数说明:
11 | *
12 | * url - 可处理的请求的url, 支持通配符和参数, 如: /{param1}/*.action/{param2}
13 | * -- 注意 --
14 | * - web-lighter 使用路径匹配方式拦截前端请求, 默认情况下, 若请求的 url 匹配模式 "/wl/*" 时将被 web-lighter 拦截并处理. 若需要更改拦截匹配模式, 请在配置文件中进行设置.
15 | * - 前端访问路径记得添加路径前缀 ( 默认为"/wl" ), 如: http://localhost:8080/wl/doSomething.action
16 | * - 本注解的 url 参数无需添加路径前缀, 如: /doSomething, 运行时 web-lighter 将会匹配 /wl/doSomething
17 | * - 虽然 url 中支持类似 RESTful Web 风格的参数, 但 web-lighter 暂未完全支持 RESTful Web 的标准方法
18 | *
19 | * format - 上行数据的格式, 默认 ParamFormat.json, Content-Type = "application/json" 时此参数无效 ( 始终被理解为JSON 格式数据)
20 | *
21 | *
22 | * @see ParamFormat
23 | */
24 | @Target(ElementType.METHOD)
25 | @Retention(RetentionPolicy.RUNTIME)
26 | public @interface Request {
27 | /**
28 | * 可处理的请求的url. 详见 {@link Request}
29 | * @return url
30 | */
31 | String url();
32 |
33 | /**
34 | * 上行参数类型. 详见 {@link Request}
35 | * @return 参数类型
36 | */
37 | ParamFormat format() default ParamFormat.json;
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/bailey/web/lighter/utils/ContentReader.java:
--------------------------------------------------------------------------------
1 | package com.bailey.web.lighter.utils;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 |
7 | /**
8 | * 读取数据的工具类
9 | *
10 | * @author Bailey
11 | */
12 | public class ContentReader {
13 |
14 | final private static int BUFFER_SIZE = 1024 * 8;
15 |
16 | /**
17 | * 从 InputStream 从读取字节流数据
18 | *
19 | * @param inputStream 输入流
20 | * @return 读取到的字节流数据
21 | * @throws IOException IOException
22 | */
23 | public static ByteArrayOutputStream readFromInputStream(InputStream inputStream) throws IOException {
24 | ByteArrayOutputStream result = new ByteArrayOutputStream();
25 | byte[] buffer = new byte[BUFFER_SIZE];
26 | int length;
27 | while ((length = inputStream.read(buffer)) != -1) {
28 | result.write(buffer, 0, length);
29 | }
30 | return result;
31 | }
32 |
33 | /**
34 | * 从 InputStream 从读取字节流数据
35 | *
36 | * @param inputStream 输入流
37 | * @return 读取到的字节流数据
38 | * @throws IOException IOException
39 | */
40 | public static byte[] readBytes(InputStream inputStream) throws IOException {
41 | return readFromInputStream(inputStream).toByteArray();
42 | }
43 |
44 | /**
45 | * 从 InputStream 从读取数据形成字符串
46 | *
47 | * @param inputStream 输入流
48 | * @param charsetName 字符集名称
49 | * @return 读取到的字符串数据
50 | * @throws IOException IOException
51 | */
52 | public static String readString(InputStream inputStream, String charsetName) throws IOException {
53 | return readFromInputStream(inputStream).toString(charsetName);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/bailey/web/lighter/utils/file/UploadResult.java:
--------------------------------------------------------------------------------
1 | package com.bailey.web.lighter.utils.file;
2 |
3 | import java.util.*;
4 |
5 | /**
6 | * 上传结果信息. 包含成功上传的文件信息集合 和 额外的参数集合
7 | * @author Bailey
8 | */
9 | public class UploadResult {
10 |
11 | private Listfrom字符集转成to字符集
47 | *
48 | * @param str 待转换的字符串
49 | * @return 转成目标字符集编码的字符串
50 | * @throws UnsupportedEncodingException 不支持的字符集编码
51 | */
52 | public String convert(String str) throws UnsupportedEncodingException {
53 | if (str == null) return null;
54 | if (from == null || to == null) return str;
55 | return new String(str.getBytes(from), to);
56 | }
57 |
58 | /**
59 | * 将字符串 str 由 Latin1 (ISO8859-1) 编码转为 UTF-8
60 | * 多数浏览器默认编码为 Latin1 (ISO8859-1), 若浏览器端提交的数据显示为乱码, 常可使用此方法处理
61 | * 62 | * @param str 源字符串 63 | * @return 使用 UTF-8 编码的字符串 64 | * @throws UnsupportedEncodingException 不支持的字符集 65 | */ 66 | public static String latin1ToUTF8(String str) throws UnsupportedEncodingException { 67 | return new String(str.getBytes(CHARSET_ISO8859_1), CHARSET_UTF_8); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/bailey/web/lighter/WebLighterConfig.java: -------------------------------------------------------------------------------- 1 | package com.bailey.web.lighter; 2 | 3 | import javax.xml.bind.JAXBContext; 4 | import javax.xml.bind.Unmarshaller; 5 | import javax.xml.bind.annotation.XmlElement; 6 | import javax.xml.bind.annotation.XmlRootElement; 7 | import java.io.File; 8 | 9 | /** 10 | * web-lighter 的总体配置 11 | * 12 | * @author Bailey 13 | */ 14 | public class WebLighterConfig { 15 | 16 | // 本工具包的名称 17 | public static final String LIB_NAME = "com.bailey.web.lighter"; 18 | 19 | // 配置文件名 20 | private static final String CONFIG_FILE_NAME = "web-lighter.xml"; 21 | 22 | // 配置信息 23 | private static Configuration config = new Configuration(); 24 | 25 | /** 26 | * 配置信息 27 | */ 28 | @XmlRootElement(name = "configuration") 29 | private static class Configuration { 30 | // HTTP请求URL前缀 31 | @XmlElement(name = "urlPrefix") 32 | public String urlPrefix = "/wl"; 33 | } 34 | 35 | /** 36 | * HTTP 请求 URL 前缀 37 | * 38 | * @return URL 前缀 39 | */ 40 | public static String getUrlPrefix() { 41 | return config.urlPrefix; 42 | } 43 | 44 | /** 45 | * 加载配置信息 46 | */ 47 | public static void loadConfiguration() { 48 | File configFile = null; 49 | try { 50 | JAXBContext context = JAXBContext.newInstance(Configuration.class); 51 | Unmarshaller unmarshaller = context.createUnmarshaller(); 52 | String rootPath = Thread.currentThread().getContextClassLoader().getResources("/").nextElement().getPath(); 53 | 54 | configFile = new File(rootPath, CONFIG_FILE_NAME); 55 | 56 | // 找不到配置文件, 直接返回(取默认值) 57 | if (!configFile.exists()) return; 58 | 59 | config = (Configuration) unmarshaller.unmarshal(configFile); 60 | } catch (Exception e) { 61 | System.err.println("[ INFO ] 读取配置文件失败 " + ((configFile == null) ? "" : "[" + configFile.getAbsolutePath()) + "]" + ", 使用默认值"); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/bailey/web/lighter/utils/file/DownloadFileInfo.java: -------------------------------------------------------------------------------- 1 | package com.bailey.web.lighter.utils.file; 2 | 3 | import java.io.*; 4 | import java.nio.file.Files; 5 | import java.nio.file.Path; 6 | import java.nio.file.Paths; 7 | 8 | /** 9 | * 下载文件的信息 10 | * 11 | * @author Bailey 12 | */ 13 | public class DownloadFileInfo { 14 | // 文件数据输入流 15 | private InputStream inputStream; 16 | // 客户端默认保存的文件名 17 | private String clientFileName; 18 | // 文件类别 19 | private String contentType; 20 | 21 | /** 22 | * 从inputStream中读取数据, 供前端下载
23 | * @param inputStream 前端保存时使用的默认文件名
24 | * @param clientFileName 文件名
25 | * @param contentType 文件的contentType, 供前端浏览器识别
26 | */
27 | public DownloadFileInfo(InputStream inputStream, String clientFileName, String contentType) {
28 | this.inputStream = inputStream;
29 | this.clientFileName = clientFileName;
30 | this.contentType = contentType;
31 | }
32 |
33 | /**
34 | * 从file中读取数据, 供前端下载
35 | * @param file 文件
36 | * @param clientFileName 前端保存时使用的默认文件名
37 | * @throws FileNotFoundException 文件未找到
38 | */
39 | public DownloadFileInfo(File file, String clientFileName) throws FileNotFoundException {
40 | this(new FileInputStream(file), clientFileName, getContentType(file));
41 | }
42 |
43 | /**
44 | * 获得文件的 ContentType
45 | *
46 | * @param file 待下载的文件
47 | * @return 文件的ContentType
48 | */
49 | public static String getContentType(File file) {
50 | String type = null;
51 | try {
52 | Path path = Paths.get(file.getAbsolutePath());
53 | type = Files.probeContentType(path);
54 | } catch (IOException e) {
55 | }
56 | return type;
57 | }
58 |
59 | public InputStream getInputStream() {
60 | return inputStream;
61 | }
62 |
63 | public String getClientFileName() {
64 | return clientFileName;
65 | }
66 |
67 | public String getContentType() {
68 | return contentType;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/bailey/web/lighter/utils/file/DownloadUtil.java:
--------------------------------------------------------------------------------
1 | package com.bailey.web.lighter.utils.file;
2 |
3 | import nl.bitwalker.useragentutils.Browser;
4 | import nl.bitwalker.useragentutils.UserAgent;
5 |
6 | import javax.servlet.ServletOutputStream;
7 | import javax.servlet.http.HttpServletRequest;
8 | import javax.servlet.http.HttpServletResponse;
9 | import java.io.InputStream;
10 | import java.io.UnsupportedEncodingException;
11 | import java.net.URLEncoder;
12 |
13 | /**
14 | * 文件下载工具类
15 | *
16 | * @author Bailey
17 | */
18 | public class DownloadUtil {
19 |
20 | private final static int BUFFER_SIZE = 1024 * 1024;
21 |
22 | /**
23 | * 对文件名进行编码. IE 和 其他浏览器使用的默认字符集编码不一致, 为避免前端文件名显示乱码, 须区别处理
24 | * @param req Request对象
25 | * @param fileName 文件名
26 | * @return 经过编码的文件名
27 | * @throws UnsupportedEncodingException 不支持的字符集
28 | */
29 | private String encodeFileName(HttpServletRequest req, String fileName) throws UnsupportedEncodingException {
30 | UserAgent userAgent = UserAgent.parseUserAgentString(req.getHeader("User-Agent"));
31 | Browser browser = userAgent.getBrowser();
32 |
33 | if (browser.getName().contains("IE")) {
34 | fileName = URLEncoder.encode(fileName, "UTF-8");
35 | } else {
36 | fileName = new String(fileName.getBytes(), "ISO-8859-1");
37 | }
38 | return fileName;
39 | }
40 |
41 | /**
42 | * 开始下载, 将数据写入输出流
43 | *
44 | * @param req Request对象
45 | * @param resp Response对象
46 | * @param fileInfo 文件信息
47 | */
48 | public void download(HttpServletRequest req, HttpServletResponse resp, DownloadFileInfo fileInfo) {
49 | try {
50 | String fileName = encodeFileName(req, fileInfo.getClientFileName());
51 |
52 | InputStream fis = fileInfo.getInputStream();
53 | int length = fis.available();
54 | ServletOutputStream sos = resp.getOutputStream();
55 |
56 | resp.setContentLength(length);
57 | resp.setContentType(fileInfo.getContentType());
58 | resp.setCharacterEncoding("UTF-8");
59 | resp.addHeader("Content-Disposition", "attachment; filename=" + fileName);
60 |
61 | byte[] buffer = new byte[BUFFER_SIZE];
62 | int readBytes = -1;
63 | while ((readBytes = fis.read(buffer, 0, BUFFER_SIZE)) != -1) {
64 | sos.write(buffer, 0, readBytes);
65 | }
66 | sos.close();
67 | fis.close();
68 | } catch (Exception e) {
69 | throw new RuntimeException(e);
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/com/bailey/web/lighter/utils/file/UploadFileInfo.java:
--------------------------------------------------------------------------------
1 | package com.bailey.web.lighter.utils.file;
2 |
3 | import java.io.File;
4 |
5 | /**
6 | * 上传的文件信息
7 | *
8 | * @author Bailey
9 | */
10 | public class UploadFileInfo {
11 | // 表单中该文件上传字段的名称
12 | private String fieldName;
13 | // 原文件名
14 | private String origFileName;
15 | // 文件大小
16 | private long fileSize;
17 | // 文件类型
18 | private String fileType;
19 | // 服务器端保存的文件名
20 | private String serverFileName;
21 | // 服务器端保存的文件相对路径(含文件名)
22 | private String serverFileRelativePath;
23 | // 服务器端保存的文件物理路径(含文件名)
24 | private String serverFileAbsolutePath;
25 |
26 | /**
27 | * @param fieldName 字段名
28 | * @param origFileName 原文件名
29 | * @param fileSize 文件字节数
30 | * @param fileType 文件MIME类型
31 | * @param serverFileName 服务器端文件名
32 | * @param serverFileRelativePath 服务器端保存的文件相对路径(含文件名)
33 | * @param serverFileAbsolutePath 服务器端保存的文件物理路径(含文件名)
34 | */
35 | public UploadFileInfo(String fieldName, String origFileName, long fileSize, String fileType, String serverFileName, String serverFileRelativePath, String serverFileAbsolutePath) {
36 | this.fieldName = fieldName;
37 | this.origFileName = origFileName;
38 | this.fileSize = fileSize;
39 | this.fileType = fileType;
40 | this.serverFileName = serverFileName;
41 | this.serverFileRelativePath = serverFileRelativePath;
42 | this.serverFileAbsolutePath =serverFileAbsolutePath;
43 | }
44 |
45 | /**
46 | * 获得表单中该文件上传字段的名称
47 | *
48 | * @return 字段名
49 | */
50 | public String getFieldName() {
51 | return fieldName;
52 | }
53 |
54 | /**
55 | * 获得原文件名
56 | *
57 | * @return 原文件名
58 | */
59 | public String getOrigFileName() {
60 | return origFileName;
61 | }
62 |
63 | /**
64 | * 获得文件字节数
65 | *
66 | * @return 字节数
67 | */
68 | public long getFileSize() {
69 | return fileSize;
70 | }
71 |
72 | /**
73 | * 获得文件MIME 类型
74 | *
75 | * @return 文件类型
76 | */
77 | public String getFileType() {
78 | return fileType;
79 | }
80 |
81 | /**
82 | * 获得服务器端存储时使用的文件名
83 | *
84 | * @return 服务器端文件名
85 | */
86 | public String getServerFileName() {
87 | return serverFileName;
88 | }
89 |
90 |
91 | /**
92 | * 获得服务器端保存的文件相对路径(含文件名)
93 | *
94 | * @return 服务器端保存的文件相对路径(含文件名)
95 | */
96 | public String getServerFileRelativePath() {
97 | return serverFileRelativePath;
98 | }
99 | /**
100 | * 获得服务器端保存的文件物理路径(含文件名)
101 | *
102 | * @return 服务器端保存的文件物理路径(含文件名)
103 | */
104 | public String getServerFileAbsolutePath() {
105 | return serverFileAbsolutePath;
106 | }
107 |
108 | @Override
109 | public String toString() {
110 | return "FileInfo{" + "origFileName='" + origFileName + '\'' + ", fileSize=" + fileSize + ", fileType='" + fileType + '\'' + ", serverFileRelativePath='" + serverFileRelativePath + '\'' + '}';
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/src/main/java/com/bailey/web/lighter/action/ActionResult.java:
--------------------------------------------------------------------------------
1 | package com.bailey.web.lighter.action;
2 |
3 | /**
4 | * 用于封装 Action 处理结果
5 | * 封装的数据包括:
6 | *7 | * code - 状态码, 正数或 0 表示成功, 默认为0; 负数表示出错 8 | * result - 回传的业务数据 9 | * message - 附加消息, 通常用于保存提示信息, 如: 出错原因 10 | * total - 全部记录数. 通常用于分页查询时返回符合条件的总记录数 11 | *12 | * 13 | * @author Bailey 14 | */ 15 | public class ActionResult { 16 | final public static int CODE_SUCCESS = 0; 17 | final public static int CODE_FAILURE_DEFAULT = -1; 18 | 19 | private int code; 20 | private Object result; 21 | private String message; 22 | private Long total; 23 | 24 | 25 | public ActionResult(int code, Object result, String message, Long total) { 26 | this.code = code; 27 | this.result = result; 28 | this.message = message; 29 | this.total = total; 30 | } 31 | 32 | public static ActionResult success(int code, Object data, String message, Long total) { 33 | if (code < 0) { 34 | ActionLogger.logger.warn("The code of SUCCESS is: " + code + ". Are you sure?"); 35 | } 36 | return new ActionResult(code, data, message, total); 37 | } 38 | 39 | public static ActionResult success(Object data, String message, Long total) { 40 | return success(CODE_SUCCESS, data, message, total); 41 | } 42 | 43 | public static ActionResult success(Object data, Long total) { 44 | return success(CODE_SUCCESS, data, null, total); 45 | } 46 | 47 | public static ActionResult success(Object data, String message) { 48 | return success(data, message, null); 49 | } 50 | 51 | public static ActionResult success(Object data) { 52 | return success(data, null, null); 53 | } 54 | 55 | public static ActionResult success() { 56 | return success(null); 57 | } 58 | 59 | 60 | public static ActionResult failure(int code, Object data, String message) { 61 | if (!(code < 0)){ 62 | ActionLogger.logger.warn("The code of FAILURE is: " + code + ". Are you sure?"); 63 | } 64 | return new ActionResult(code, data, message, null); 65 | } 66 | 67 | public static ActionResult failure(Object data, String message) { 68 | return failure(CODE_FAILURE_DEFAULT, data, message); 69 | } 70 | 71 | public static ActionResult failure(String message) { 72 | return failure(null, message); 73 | } 74 | 75 | public static ActionResult failure() { 76 | return failure(null, null); 77 | } 78 | 79 | 80 | public int getCode() { 81 | return code; 82 | } 83 | 84 | public void setCode(int code) { 85 | this.code = code; 86 | } 87 | 88 | public Object getResult() { 89 | return result; 90 | } 91 | 92 | public void setResult(Object data) { 93 | this.result = result; 94 | } 95 | 96 | public String getMessage() { 97 | return message; 98 | } 99 | 100 | public void setMessage(String message) { 101 | this.message = message; 102 | } 103 | 104 | public Long getTotal() { 105 | return total; 106 | } 107 | 108 | public void setTotal(Long total) { 109 | this.total = total; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/bailey/web/lighter/utils/DateParser.java: -------------------------------------------------------------------------------- 1 | package com.bailey.web.lighter.utils; 2 | 3 | import com.bailey.web.lighter.WebLighterConfig; 4 | import com.bailey.web.lighter.vo.SearchCriteria; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.text.DateFormat; 10 | import java.text.ParseException; 11 | import java.text.SimpleDateFormat; 12 | import java.util.Date; 13 | import java.util.Locale; 14 | import java.util.TimeZone; 15 | 16 | /** 17 | * 日期型数据解析工具类 18 | */ 19 | public class DateParser { 20 | 21 | private static final Logger logger = LoggerFactory.getLogger(WebLighterConfig.LIB_NAME + ".utils.DateParser"); 22 | 23 | public static final String UTC_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; 24 | 25 | public static final DateFormat UTC_FORMAT; 26 | public static final DateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd", Locale.getDefault()); 27 | public static final DateFormat SIMPLE_DATE_TIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault()); 28 | 29 | 30 | static { 31 | UTC_FORMAT = new SimpleDateFormat(UTC_FORMAT_STRING, Locale.getDefault()); 32 | UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); 33 | } 34 | 35 | /** 36 | * 将字符串表示的 ISO 日期时间转为 Date 类型 37 | * 38 | * @param dateStr 时间字符串 39 | */ 40 | public static Date parseDate(String dateStr) { 41 | if (dateStr == null) return null; 42 | try { 43 | return UTC_FORMAT.parse(dateStr); 44 | } catch (ParseException e) { 45 | logger.warn("解析时间日期出错", e); 46 | return null; 47 | } 48 | } 49 | 50 | /** 51 | * 将字符串表示的 ISO 日期时间转为 Date 类型 52 | * 53 | * @param dateStrArr 时间字符串数组 54 | */ 55 | public static Date[] parseDate(String... dateStrArr) { 56 | if (dateStrArr == null) return null; 57 | Date[] dates = new Date[dateStrArr.length]; 58 | for (int i = 0; i < dateStrArr.length; i++) { 59 | dates[i] = parseDate(dateStrArr[i]); 60 | } 61 | return dates; 62 | } 63 | 64 | 65 | /** 66 | * 将字符串时段转为日期数组 67 | * 68 | * @param dateRange 形如"2018/11/17 - 2018/12/31" 69 | */ 70 | public static Date[] parseDateRange(String dateRange) throws ParseException { 71 | if (StringUtils.isBlank(dateRange)) return null; 72 | String[] dateStrArr = dateRange.split("-"); 73 | if (dateStrArr.length < 2) throw new ParseException("日期范围格式错误, 应为 yyyy/MM/dd - yyyy/MM/dd", 0); 74 | return new Date[]{dateStrArr[0] == null ? null : SIMPLE_DATE_FORMAT.parse(dateStrArr[0]), dateStrArr[1] == null ? null : SIMPLE_DATE_FORMAT.parse(dateStrArr[1])}; 75 | } 76 | 77 | /** 78 | * 将检索条件中的 ISO 日期时间转为 Date 类型数组. 79 | *
80 | * 默认字段名分别为 dateMin, dateMax
81 | *
82 | * @param criteria 时间字符串数组
83 | */
84 | public static Date[] parseDate(SearchCriteria criteria) {
85 | return parseDate(criteria, "dateMin", "dateMax");
86 | }
87 |
88 | /**
89 | * 将检索条件中的 ISO 日期时间转为 Date 类型数组
90 | *
91 | * @param criteria 时间字符串数组
92 | * @param key 字段名
93 | */
94 | public static Date[] parseDate(SearchCriteria criteria, String... key) {
95 | String[] dateStrArr = new String[key.length];
96 | for (int i = 0; i < key.length; i++) {
97 | dateStrArr[i] = criteria.get(key[i]);
98 | }
99 | return parseDate(dateStrArr);
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/java/com/bailey/web/lighter/action/RequestHandler.java:
--------------------------------------------------------------------------------
1 | package com.bailey.web.lighter.action;
2 |
3 | import com.bailey.web.lighter.annotation.Request;
4 |
5 | import java.lang.reflect.Method;
6 | import java.util.ArrayList;
7 | import java.util.LinkedHashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.util.regex.Matcher;
11 | import java.util.regex.Pattern;
12 |
13 | /**
14 | * HttpServletRequest 处理器信息
15 | *
16 | * @author Bailey
17 | */
18 | public class RequestHandler {
19 | // 可处理的HttpServletRequest的Url模式,
20 | private String urlPattern;
21 | // 用于执行HttpServletRequest处理的Action类
22 | private Class extends ActionSupport> actionClass;
23 | // Action类中用于HttpServletRequest处理的具体方法
24 | private Method method;
25 |
26 |
27 | // 用于提取URL中变量名的Regular Expression Pattern
28 | final private static Pattern paramRegex = Pattern.compile("\\{(\\w+)\\}");
29 | // 编译完成的urlPattern
30 | private Pattern urlRegex;
31 | // url中的占位参数
32 | private List 将值处理为String[] 是为了和表单提交的数据形式一致, 以便后续处理 按条件搜索Class, 同时缓存这些Class的信息. 此后可使用如下方法获得满足条件的Class集合 进行Class搜索时将搜索所有package下的Class, 但忽略jar中的Class.
21 | * - getAllClasses() : 返回所有类的集合
22 | * - getClassesByAnnotation() : 返回标注了指定注解的类集合
23 | * - getSubClasses() : 返回指定 超类的子类 或 实现了指定接口的类 组成的集合
24 | *
25 | *
26 | * @author Bailey
27 | */
28 | public class ClassHelper {
29 | private String packageName;
30 | private boolean isRecursive;
31 | private boolean isIncludeJar;
32 |
33 | // 是否已经搜索并缓存过所有类
34 | private boolean isSearched = false;
35 |
36 | // 所有类集合缓存
37 | private List
26 | * - 根据 Request 的 URI 找到处理该 Request 的函数
27 | * - 实例化处理 Request 的 Action 对象, 并调用相应的处理函数. 调用处理函数前将自动解析上行参数 ( JSON / Text), 并将在调用处理函数时作为参数注入.
28 | * - 支持多文件上传 ( 可同时携带数据 )
29 | * - 调用 Request 处理函数时自动实例化并注入 Service 之类的对象 ( 使用 @Inject )
30 | *
31 | *
32 | * @author Bailey
33 | * @see Request
34 | * @see Inject
35 | * @see Param
36 | * @see Upload
37 | * @see Download
38 | */
39 | public class ActionHelper {
40 | final private static List