工具类
package my.util;import java.net.MalformedURLException;import java.net.URL;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.beanutils.ConvertUtils;import org.apache.commons.lang.StringUtils;import org.apache.commons.lang.math.NumberUtils;/** * 用于处理HTTP请求的工具类 * @author Winter Lau */public class RequestUtils {/** * 获取客户端IP地址,此方法用在proxy环境中 * @param req * @return */public static String getRemoteAddr(HttpServletRequest req) {String ip = req.getHeader("X-Forwarded-For");if(StringUtils.isNotBlank(ip)){String[] ips = StringUtils.split(ip,',');if(ips!=null){for(String tmpip : ips){if(StringUtils.isBlank(tmpip))continue;tmpip = tmpip.trim();if(isIPAddr(tmpip) && !tmpip.startsWith("10.") && !tmpip.startsWith("192.168.") && !"127.0.0.1".equals(tmpip)){return tmpip.trim();}}}}ip = req.getHeader("x-real-ip");if(isIPAddr(ip))return ip;ip = req.getRemoteAddr();if(ip.indexOf('.')==-1)ip = "127.0.0.1";return ip;}/** * 判断是否为搜索引擎 * @param req * @return */public static boolean isRobot(HttpServletRequest req){String ua = req.getHeader("user-agent");if(StringUtils.isBlank(ua)) return false;return (ua != null&& (ua.indexOf("Baiduspider") != -1 || ua.indexOf("Googlebot") != -1|| ua.indexOf("sogou") != -1|| ua.indexOf("sina") != -1|| ua.indexOf("iaskspider") != -1|| ua.indexOf("ia_archiver") != -1|| ua.indexOf("Sosospider") != -1|| ua.indexOf("YoudaoBot") != -1|| ua.indexOf("yahoo") != -1 || ua.indexOf("yodao") != -1|| ua.indexOf("MSNBot") != -1|| ua.indexOf("spider") != -1|| ua.indexOf("Twiceler") != -1|| ua.indexOf("Sosoimagespider") != -1|| ua.indexOf("naver.com/robots") != -1|| ua.indexOf("Nutch") != -1|| ua.indexOf("spider") != -1));}/** * 获取COOKIE * * @param name */public static Cookie getCookie(HttpServletRequest request, String name) {Cookie[] cookies = request.getCookies();if(cookies == null)return null;for (Cookie ck : cookies) {if (StringUtils.equalsIgnoreCase(name,ck.getName())) return ck;}return null;}/** * 获取COOKIE * * @param name */public static String getCookieValue(HttpServletRequest request, String name) {Cookie[] cookies = request.getCookies();if(cookies == null)return null;for (Cookie ck : cookies) {if (StringUtils.equalsIgnoreCase(name,ck.getName())) return ck.getValue();}return null;}/** * 设置COOKIE * * @param name * @param value * @param maxAge */public static void setCookie(HttpServletRequest request, HttpServletResponse response, String name,String value, int maxAge) {setCookie(request,response,name,value,maxAge,true);}/** * 设置COOKIE * * @param name * @param value * @param maxAge */public static void setCookie(HttpServletRequest request, HttpServletResponse response, String name,String value, int maxAge, boolean all_sub_domain) {Cookie cookie = new Cookie(name, value);cookie.setMaxAge(maxAge);if(all_sub_domain){String serverName = request.getServerName();String domain = getDomainOfServerName(serverName);if(domain!=null && domain.indexOf('.')!=-1){cookie.setDomain('.' + domain);}}cookie.setPath("/");response.addCookie(cookie);}public static void deleteCookie(HttpServletRequest request,HttpServletResponse response, String name, boolean all_sub_domain) {setCookie(request,response,name,"",0,all_sub_domain);}/** * 获取用户访问URL中的根域名 * 例如: www.dlog.cn -> dlog.cn * @param req * @return */public static String getDomainOfServerName(String host){if(isIPAddr(host))return null;String[] names = StringUtils.split(host, '.');int len = names.length;if(len==1) return null;if(len==3){return makeup(names[len-2],names[len-1]);}if(len>3){String dp = names[len-2];if(dp.equalsIgnoreCase("com")||dp.equalsIgnoreCase("gov")||dp.equalsIgnoreCase("net")||dp.equalsIgnoreCase("edu")||dp.equalsIgnoreCase("org"))return makeup(names[len-3],names[len-2],names[len-1]);elsereturn makeup(names[len-2],names[len-1]);}return host;}/** * 判断字符串是否是一个IP地址 * @param addr * @return */public static boolean isIPAddr(String addr){if(StringUtils.isEmpty(addr))return false;String[] ips = StringUtils.split(addr, '.');if(ips.length != 4)return false;try{int ipa = Integer.parseInt(ips[0]);int ipb = Integer.parseInt(ips[1]);int ipc = Integer.parseInt(ips[2]);int ipd = Integer.parseInt(ips[3]);return ipa >= 0 && ipa <= 255 && ipb >= 0 && ipb <= 255 && ipc >= 0&& ipc <= 255 && ipd >= 0 && ipd <= 255;}catch(Exception e){}return false;}private static String makeup(String...ps){StringBuilder s = new StringBuilder();for(int idx = 0; idx < ps.length; idx++){if(idx > 0)s.append('.');s.append(ps[idx]);}return s.toString();}/** * 获取HTTP端口 * @param req * @return * @throws MalformedURLException */public static int getHttpPort(HttpServletRequest req) {try {return new URL(req.getRequestURL().toString()).getPort();} catch (MalformedURLException excp) {return 80;}}/** * 获取浏览器提交的整形参数 * @param param * @param defaultValue * @return */public static int getParam(HttpServletRequest req, String param, int defaultValue){return NumberUtils.toInt(req.getParameter(param), defaultValue);}/** * 获取浏览器提交的整形参数 * @param param * @param defaultValue * @return */public static long getParam(HttpServletRequest req, String param, long defaultValue){return NumberUtils.toLong(req.getParameter(param), defaultValue);}public static long[] getParamValues(HttpServletRequest req, String name){String[] values = req.getParameterValues(name);if(values==null) return null;return (long[])ConvertUtils.convert(values, long.class);}/** * 获取浏览器提交的字符串参?? * @param param * @param defaultValue * @return */public static String getParam(HttpServletRequest req, String param, String defaultValue){String value = req.getParameter(param);return (StringUtils.isEmpty(value))?defaultValue:value;}}
package my.mvc;import java.io.*;import java.lang.reflect.*;import java.net.URLDecoder;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;import my.db.DBException;import my.util.ResourceUtils;import org.apache.commons.lang.StringUtils;import org.apache.commons.lang.math.NumberUtils;/** * 业务处理方法入口,URI的映射逻辑: * /action/xxxxxx/xxxx -> com.dlog4j.action.XxxxxxAction.xxxx(req,res) * <pre>林花谢了春红,太匆匆,无奈朝来寒雨晚来风。胭脂泪,相留醉,几时重,自是人生长恨水长东。 * </pre> * @author Winter Lau (http://my.oschina.net/javayou)<br> */public final class ActionServlet extends HttpServlet {private final static String ERROR_PAGE = "error_page";private final static String GOTO_PAGE = "goto_page";private final static String THIS_PAGE = "this_page";private final static String ERROR_MSG = "error_msg";private final static String UTF_8 = "utf-8";private List<String> action_packages = null;private final static ThreadLocal<Boolean> g_json_enabled = new ThreadLocal<Boolean>();@Overridepublic void init() throws ServletException {String tmp = getInitParameter("packages");action_packages = Arrays.asList(StringUtils.split(tmp,','));String initial_actions = getInitParameter("initial_actions");for(String action : StringUtils.split(initial_actions,','))try {_LoadAction(action);} catch (Exception e) {log("Failed to initial action : " + action, e);}}@Overridepublic void destroy() {for(Object action : actions.values()){try{Method dm = action.getClass().getMethod("destroy");if(dm != null){dm.invoke(action);log("!!!!!!!!! " + action.getClass().getSimpleName() + " destroy !!!!!!!!!");}}catch(NoSuchMethodException e){}catch(Exception e){log("Unabled to destroy action: " + action.getClass().getSimpleName(), e);}}super.destroy();}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {process(RequestContext.get(), false);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {process(RequestContext.get(), true);}/** * 执行Action方法并进行返回处理、异常处理 * @param req * @param resp * @param is_post * @throws ServletException * @throws IOException */protected void process(RequestContext req, boolean is_post) throws ServletException, IOException {try{req.response().setContentType("text/html;charset=utf-8");if(_process(req, is_post)){ String gp = req.param(GOTO_PAGE);if(StringUtils.isNotBlank(gp))req.redirect(gp);}}catch(InvocationTargetException e){Throwable t = e.getCause();if(t instanceof ActionException)handleActionException(req, (ActionException)t);else if(t instanceof DBException)handleDBException(req, (DBException)t);elsethrow new ServletException(t);}catch(ActionException t){handleActionException(req, t);}catch(IOException e){throw e;}catch(DBException e){handleDBException(req, e);}catch(Exception e){log("Exception in action process.", e);throw new ServletException(e);}finally{g_json_enabled.remove();}}/** * Action业务异常 * @param req * @param resp * @param t * @throws ServletException * @throws IOException */protected void handleActionException(RequestContext req, ActionException t)throws ServletException, IOException {handleException(req, t.getMessage());}protected void handleDBException(RequestContext req, DBException e) throws ServletException, IOException {log("DBException in action process.", e);handleException(req, ResourceUtils.getString("error", "database_exception", e.getCause().getMessage()));}/** * URL解码 * * @param url * @param charset * @return */private static String _DecodeURL(String url, String charset) {if (StringUtils.isEmpty(url))return "";try {return URLDecoder.decode(url, charset);} catch (Exception e) {}return url;}protected void handleException(RequestContext req, String msg) throws ServletException, IOException {String ep = req.param(ERROR_PAGE);if(StringUtils.isNotBlank(ep)){if(ep.charAt(0)=='%')ep = _DecodeURL(ep, UTF_8);ep = ep.trim();if(ep.charAt(0)!='/'){req.redirect(req.contextPath()+"/");}else{req.request().setAttribute(ERROR_MSG, msg);req.forward(ep.trim());}}else{if(g_json_enabled.get())req.output_json("msg", msg);elsereq.print(msg);}}/** * 业务逻辑处理 * @param req * @param resp * @param is_post_method * @throws IllegalAccessException * @throws InstantiationException * @throws IOException * @throws ServletException * @throws IOException * @throws InvocationTargetException * @throws IllegalArgumentException */private boolean _process(RequestContext req, boolean is_post) throws InstantiationException,IllegalAccessException, IOException, IllegalArgumentException,InvocationTargetException{String requestURI = req.uri();String[] parts = StringUtils.split(requestURI, '/');if(parts.length<2){req.not_found();return false;}//加载Action类Object action = this._LoadAction(parts[1]);if(action == null){req.not_found();return false;}String action_method_name = (parts.length>2)?parts[2]:"index";Method m_action = this._GetActionMethod(action, action_method_name);if(m_action == null){req.not_found();return false;}//判断action方法是否只支持POSTif (!is_post && m_action.isAnnotationPresent(Annotation.PostMethod.class)){req.not_found();return false;}g_json_enabled.set(m_action.isAnnotationPresent(Annotation.JSONOutputEnabled.class));if(m_action.isAnnotationPresent(Annotation.UserRoleRequired.class)){IUser loginUser = req.user();if(loginUser == null){String this_page = req.param(THIS_PAGE, "");throw req.error("user_not_login", this_page);}if(loginUser.IsBlocked())throw req.error("user_blocked");Annotation.UserRoleRequired urr = (Annotation.UserRoleRequired)m_action.getAnnotation(Annotation.UserRoleRequired.class);if(loginUser.getRole() < urr.role())throw req.error("user_role_deny");}//调用Action方法之准备参数int arg_c = m_action.getParameterTypes().length;switch(arg_c){case 0: // login()m_action.invoke(action);break ;case 1:m_action.invoke(action, req);break;case 2: // login(HttpServletRequest req, HttpServletResponse res)m_action.invoke(action, req.request(), req.response());break ;case 3: // login(HttpServletRequest req, HttpServletResponse res, String[] extParams)StringBuilder args = new StringBuilder();for(int i=3;i<parts.length;i++){if(StringUtils.isBlank(parts[i]))continue;if(args.length() > 0)args.append('/');args.append(parts[i]);}boolean isLong = m_action.getParameterTypes()[2].equals(long.class);m_action.invoke(action, req.request(), req.response(), isLong ? NumberUtils.toLong(args.toString(), -1L) : args.toString());break ;default:req.not_found();return false;}return true;}/** * 加载Action类 * @param act_name * @return * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException */protected Object _LoadAction(String act_name) throws InstantiationException,IllegalAccessException {Object action = actions.get(act_name);if(action == null){for(String pkg : action_packages){String cls = pkg + '.' + StringUtils.capitalize(act_name) + "Action";action = _LoadActionOfFullname(act_name, cls);if(action != null)break;}}return action ;}private Object _LoadActionOfFullname(String act_name, String cls) throws IllegalAccessException, InstantiationException {Object action = null;try {action = Class.forName(cls).newInstance();try{Method action_init_method = action.getClass().getMethod("init", ServletContext.class);action_init_method.invoke(action, getServletContext());}catch(NoSuchMethodException e){}catch(InvocationTargetException excp) {excp.printStackTrace();}if(!actions.containsKey(act_name)){synchronized(actions){actions.put(act_name, action);}}} catch (ClassNotFoundException excp) {}return action;}/** * 获取名为{method}的方法 * @param action * @param method * @return */private Method _GetActionMethod(Object action, String method) {String key = action.getClass().getSimpleName() + '.' + method;Method m = methods.get(key);if(m != null) return m;for(Method m1 : action.getClass().getMethods()){if(m1.getModifiers()==Modifier.PUBLIC && m1.getName().equals(method)){synchronized(methods){methods.put(key, m1);}return m1 ;}}return null;}private final static HashMap<String, Object> actions = new HashMap<String, Object>();private final static HashMap<String, Method> methods = new HashMap<String, Method>();}
package my.mvc;import java.io.*;import java.net.*;import java.text.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;import my.util.CryptUtils;import my.util.Multimedia;import my.util.RequestUtils;import my.util.ResourceUtils;import net.oschina.beans.User;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.beanutils.ConvertUtils;import org.apache.commons.beanutils.Converter;import org.apache.commons.beanutils.converters.SqlDateConverter;import org.apache.commons.codec.binary.Base64;import org.apache.commons.io.FileUtils;import org.apache.commons.lang.RandomStringUtils;import org.apache.commons.lang.StringUtils;import org.apache.commons.lang.math.NumberUtils;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/** * 请求上下文 * @author Winter Lau * @date 2010-1-13 下午04:18:00 */public class RequestContext {private final static Log log = LogFactory.getLog(RequestContext.class);private final static int MAX_FILE_SIZE = 10*1024*1024; private final static String UTF_8 = "UTF-8";private final static ThreadLocal<RequestContext> contexts = new ThreadLocal<RequestContext>();private final static boolean isResin;private final static String upload_tmp_path;private final static String TEMP_UPLOAD_PATH_ATTR_NAME = "$OSCHINA_TEMP_UPLOAD_PATH$";private static String webroot = null;private ServletContext context;private HttpSession session;private HttpServletRequest request;private HttpServletResponse response;private Map<String, Cookie> cookies;static {webroot = getWebrootPath();isResin = _CheckResinVersion();//上传的临时目录upload_tmp_path = webroot + "WEB-INF" + File.separator + "tmp" + File.separator;try {FileUtils.forceMkdir(new File(upload_tmp_path));} catch (IOException excp) {}//BeanUtils对时间转换的初始化设置ConvertUtils.register(new SqlDateConverter(null), java.sql.Date.class);ConvertUtils.register(new Converter(){SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d");SimpleDateFormat sdf_time = new SimpleDateFormat("yyyy-M-d H:m");@SuppressWarnings("rawtypes")public Object convert(Class type, Object value) {if(value == null) return null; if (value instanceof Date) return (value); try { return sdf_time.parse(value.toString()); } catch (ParseException e) { try {return sdf.parse(value.toString());} catch (ParseException e1) {return null;} }}}, java.util.Date.class);}private final static String getWebrootPath() {String root = RequestContext.class.getResource("/").getFile();try {root = new File(root).getParentFile().getParentFile().getCanonicalPath();root += File.separator;} catch (IOException e) {throw new RuntimeException(e);}return root;}/** * 初始化请求上下文 * @param ctx * @param req * @param res */public static RequestContext begin(ServletContext ctx, HttpServletRequest req, HttpServletResponse res) {RequestContext rc = new RequestContext();rc.context = ctx;rc.request = _AutoUploadRequest(_AutoEncodingRequest(req));rc.response = res;rc.response.setCharacterEncoding(UTF_8);rc.session = req.getSession(false);rc.cookies = new HashMap<String, Cookie>();Cookie[] cookies = req.getCookies();if(cookies != null)for(Cookie ck : cookies) {rc.cookies.put(ck.getName(), ck);}contexts.set(rc);return rc;}/** * 返回Web应用的路径 * @return */public static String root() { return webroot; }/** * 获取当前请求的上下文 * @return */public static RequestContext get(){return contexts.get();}public void end() {String tmpPath = (String)request.getAttribute(TEMP_UPLOAD_PATH_ATTR_NAME);if(tmpPath != null){try {FileUtils.deleteDirectory(new File(tmpPath));} catch (IOException e) {log.fatal("Failed to cleanup upload directory: " + tmpPath, e);}}this.context = null;this.request = null;this.response = null;this.session = null;this.cookies = null;contexts.remove();}public Locale locale(){ return request.getLocale(); }public void closeCache(){ header("Pragma","No-cache"); header("Cache-Control","no-cache"); header("Expires", 0L);}/** * 自动编码处理 * @param req * @return */private static HttpServletRequest _AutoEncodingRequest(HttpServletRequest req) {if(req instanceof RequestProxy)return req;HttpServletRequest auto_encoding_req = req;if("POST".equalsIgnoreCase(req.getMethod())){try {auto_encoding_req.setCharacterEncoding(UTF_8);} catch (UnsupportedEncodingException e) {}}else if(!isResin)auto_encoding_req = new RequestProxy(req, UTF_8);return auto_encoding_req;}/** * 自动文件上传请求的封装 * @param req * @return */private static HttpServletRequest _AutoUploadRequest(HttpServletRequest req){if(_IsMultipart(req)){String path = upload_tmp_path + RandomStringUtils.randomAlphanumeric(10);File dir = new File(path);if(!dir.exists() && !dir.isDirectory())dir.mkdirs();try{req.setAttribute(TEMP_UPLOAD_PATH_ATTR_NAME,path);return new MultipartRequest(req, dir.getCanonicalPath(), MAX_FILE_SIZE, UTF_8);}catch(NullPointerException e){}catch(IOException e){log.fatal("Failed to save upload files into temp directory: " + path, e);}}return req;}public long id() {return param("id", 0L);}public String ip(){return RequestUtils.getRemoteAddr(request);}@SuppressWarnings("unchecked")public Enumeration<String> params() {return request.getParameterNames();}public String param(String name, String...def_value) {String v = request.getParameter(name);return (v!=null)?v:((def_value.length>0)?def_value[0]:null);}public long param(String name, long def_value) {return NumberUtils.toLong(param(name), def_value);}public int param(String name, int def_value) {return NumberUtils.toInt(param(name), def_value);}public byte param(String name, byte def_value) {return (byte)NumberUtils.toInt(param(name), def_value);}public String[] params(String name) {return request.getParameterValues(name);}public long[] lparams(String name){String[] values = params(name);if(values==null) return null;return (long[])ConvertUtils.convert(values, long.class);}public String uri(){return request.getRequestURI();}public String contextPath(){return request.getContextPath();}public void redirect(String uri) throws IOException {response.sendRedirect(uri);}public void forward(String uri) throws ServletException, IOException {RequestDispatcher rd = context.getRequestDispatcher(uri);rd.forward(request, response);}public void include(String uri) throws ServletException, IOException {RequestDispatcher rd = context.getRequestDispatcher(uri);rd.include(request, response);}public boolean isUpload(){return (request instanceof MultipartRequest);}public File file(String fieldName) {if(request instanceof MultipartRequest)return ((MultipartRequest)request).getFile(fieldName);return null;}public File image(String fieldname) {File imgFile = file(fieldname);return (imgFile!=null&&Multimedia.isImageFile(imgFile.getName()))?imgFile:null;}public boolean isRobot(){return RequestUtils.isRobot(request);}public ActionException fromResource(String bundle, String key, Object...args){String res = ResourceUtils.getStringForLocale(request.getLocale(), bundle, key, args);return new ActionException(res);}public ActionException error(String key, Object...args){return fromResource("error", key, args);}/** * 输出信息到浏览器 * @param msg * @throws IOException */public void print(Object msg) throws IOException {if(!UTF_8.equalsIgnoreCase(response.getCharacterEncoding()))response.setCharacterEncoding(UTF_8);response.getWriter().print(msg);}public void output_json(String[] key, Object[] value) throws IOException {StringBuilder json = new StringBuilder("{");for(int i=0;i<key.length;i++){if(i>0)json.append(',');boolean isNum = value[i] instanceof Number ;json.append(""");json.append(key[i]);json.append("":");if(!isNum) json.append(""");json.append(value[i]);if(!isNum) json.append(""");}json.append("}");print(json.toString());}public void output_json(String key, Object value) throws IOException {output_json(new String[]{key}, new Object[]{value});}public void error(int code, String...msg) throws IOException {if(msg.length>0)response.sendError(code, msg[0]);elseresponse.sendError(code);}public void forbidden() throws IOException { error(HttpServletResponse.SC_FORBIDDEN); }public void not_found() throws IOException { error(HttpServletResponse.SC_NOT_FOUND); }public ServletContext context() { return context; }public HttpSession session() { return session; }public HttpSession session(boolean create) { return (session==null && create)?(session=request.getSession()):session; }public Object sessionAttr(String attr) {HttpSession ssn = session();return (ssn!=null)?ssn.getAttribute(attr):null;}public HttpServletRequest request() { return request; }public HttpServletResponse response() { return response; }public Cookie cookie(String name) { return cookies.get(name); }public void cookie(String name, String value, int max_age, boolean all_sub_domain) {RequestUtils.setCookie(request, response, name, value, max_age, all_sub_domain);}public void deleteCookie(String name,boolean all_domain) { RequestUtils.deleteCookie(request, response, name, all_domain); }public String header(String name) { return request.getHeader(name); }public void header(String name, String value) { response.setHeader(name, value); }public void header(String name, int value) { response.setIntHeader(name, value); }public void header(String name, long value) { response.setDateHeader(name, value); }/** * 将HTTP请求参数映射到bean对象中 * @param req * @param beanClass * @return * @throws Exception */public <T> T form(Class<T> beanClass) {try{T bean = beanClass.newInstance();BeanUtils.populate(bean, request.getParameterMap());return bean;}catch(Exception e) {throw new ActionException(e.getMessage());}}/** * 返回当前登录的用户资料 * @return */public IUser user() {return User.GetLoginUser(request);}/** * 保存登录信息 * @param req * @param res * @param user * @param save */public void saveUserInCookie(IUser user, boolean save) {String new_value = _GenLoginKey(user, ip(), header("user-agent"));int max_age = save ? MAX_AGE : -1;deleteCookie(COOKIE_LOGIN, true);cookie(COOKIE_LOGIN,new_value,max_age,true);}public void deleteUserInCookie() {deleteCookie(COOKIE_LOGIN, true);}/** * 3.0 以上版本的 Resin 无需对URL参数进行转码 * @return */private final static boolean _CheckResinVersion() {try{Class<?> verClass = Class.forName("com.caucho.Version");String ver = (String)verClass.getDeclaredField("VERSION").get(verClass);String mainVer = ver.substring(0, ver.lastIndexOf('.'));/**float fVer = Float.parseFloat(mainVer);System.out.println("----------------> " + fVer);*/return Float.parseFloat(mainVer) > 3.0;}catch(Throwable t) {}return false;}/** * 自动解码 * @author liudong */private static class RequestProxy extends HttpServletRequestWrapper {private String uri_encoding; RequestProxy(HttpServletRequest request, String encoding){super(request);this.uri_encoding = encoding;}/** * 重载getParameter */public String getParameter(String paramName) {String value = super.getParameter(paramName);return _DecodeParamValue(value);}/** * 重载getParameterMap */@SuppressWarnings({ "unchecked", "rawtypes" })public Map<String, Object> getParameterMap() {Map params = super.getParameterMap();HashMap<String, Object> new_params = new HashMap<String, Object>();Iterator<String> iter = params.keySet().iterator();while(iter.hasNext()){String key = (String)iter.next();Object oValue = params.get(key);if(oValue.getClass().isArray()){String[] values = (String[])params.get(key);String[] new_values = new String[values.length];for(int i=0;i<values.length;i++)new_values[i] = _DecodeParamValue(values[i]);new_params.put(key, new_values);}else{String value = (String)params.get(key);String new_value = _DecodeParamValue(value);if(new_value!=null)new_params.put(key,new_value);}}return new_params;}/** * 重载getParameterValues */public String[] getParameterValues(String arg0) {String[] values = super.getParameterValues(arg0);for(int i=0;values!=null&&i<values.length;i++)values[i] = _DecodeParamValue(values[i]);return values;}/** * 参数转码 * @param value * @return */private String _DecodeParamValue(String value){if (StringUtils.isBlank(value) || StringUtils.isBlank(uri_encoding)|| StringUtils.isNumeric(value))return value;try{return new String(value.getBytes("8859_1"), uri_encoding);}catch(Exception e){}return value;}}private static boolean _IsMultipart(HttpServletRequest req) {return ((req.getContentType() != null) && (req.getContentType().toLowerCase().startsWith("multipart")));}/** * 生成用户登录标识字符串 * @param user * @param ip * @param user_agent * @return */public static String _GenLoginKey(IUser user, String ip, String user_agent) {StringBuilder sb = new StringBuilder();sb.append(user.getId());sb.append('|');sb.append(user.getPwd());sb.append('|');sb.append(ip);sb.append('|');sb.append((user_agent==null)?0:user_agent.hashCode());sb.append('|');sb.append(System.currentTimeMillis());return _Encrypt(sb.toString());}/** * 加密 * @param value * @return * @throws Exception */private static String _Encrypt(String value) {byte[] data = CryptUtils.encrypt(value.getBytes(), E_KEY);try{return URLEncoder.encode(new String(Base64.encodeBase64(data)), UTF_8);}catch(UnsupportedEncodingException e){return null;}}/** * 解密 * @param value * @return * @throws Exception */private static String _Decrypt(String value) {try {value = URLDecoder.decode(value,UTF_8);if(StringUtils.isBlank(value)) return null;byte[] data = Base64.decodeBase64(value.getBytes());return new String(CryptUtils.decrypt(data, E_KEY));} catch (UnsupportedEncodingException excp) {return null;}}/** * 从cookie中读取保存的用户信息 * @param req * @return */public IUser getUserFromCookie() {try{Cookie cookie = cookie(COOKIE_LOGIN);if(cookie!=null && StringUtils.isNotBlank(cookie.getValue())){return userFromUUID(cookie.getValue());}}catch(Exception e){}return null;}/** * 从cookie中读取保存的用户信息 * @param req * @return */public IUser userFromUUID(String uuid) {if(StringUtils.isBlank(uuid))return null;String ck = _Decrypt(uuid);final String[] items = StringUtils.split(ck, '|');if(items.length == 5){String ua = header("user-agent");int ua_code = (ua==null)?0:ua.hashCode();int old_ua_code = Integer.parseInt(items[3]);if(ua_code == old_ua_code){return new IUser(){public boolean IsBlocked() { return false; }public long getId() { return NumberUtils.toLong(items[0],-1L); }public String getPwd() { return items[1]; }public byte getRole() { return IUser.ROLE_GENERAL; }};}}return null;}public final static String COOKIE_LOGIN = "oscid";private final static int MAX_AGE = 86400 * 365;private final static byte[] E_KEY = new byte[]{'1','2','3','4','5','6','7','8'};}
package my.db;import java.io.Serializable;import java.math.BigInteger;import java.sql.*;import java.util.*;import my.cache.CacheManager;import net.oschina.Configurations;import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.handlers.*;import org.apache.commons.lang.ArrayUtils;/** * 数据库查询助手 * @author Winter Lau<br> */@SuppressWarnings("unchecked")public class QueryHelper {private final static QueryRunner _g_runner = new QueryRunner();private final static ColumnListHandler _g_columnListHandler = new ColumnListHandler(){@Overrideprotected Object handleRow(ResultSet rs) throws SQLException {Object obj = super.handleRow(rs);if(obj instanceof BigInteger)return ((BigInteger)obj).longValue();return obj;}};private final static ScalarHandler _g_scaleHandler = new ScalarHandler(){@Overridepublic Object handle(ResultSet rs) throws SQLException {Object obj = super.handle(rs);if(obj instanceof BigInteger)return ((BigInteger)obj).longValue();return obj;}};private final static List<Class<?>> PrimitiveClasses = new ArrayList<Class<?>>(){{add(Long.class);add(Integer.class);add(String.class);add(java.util.Date.class);add(java.sql.Date.class);add(java.sql.Timestamp.class);}};private final static boolean _IsPrimitive(Class<?> cls) {return cls.isPrimitive() || PrimitiveClasses.contains(cls) ;}/** * 获取数据库连接 * @return */public static Connection getConnection() {try{return Configurations.getConnection();}catch(SQLException e){throw new DBException(e);}}/** * 读取某个对象 * @param sql * @param params * @return */@SuppressWarnings("rawtypes")public static <T> T read(Class<T> beanClass, String sql, Object...params) {try{return (T)_g_runner.query(getConnection(), sql, _IsPrimitive(beanClass)?_g_scaleHandler:new BeanHandler(beanClass), params);}catch(SQLException e){throw new DBException(e);}}public static <T> T read_cache(Class<T> beanClass, String cache, Serializable key, String sql, Object...params) {T obj = (T)CacheManager.get(cache, key);if(obj == null){obj = read(beanClass, sql, params);CacheManager.set(cache, key, (Serializable)obj);}return obj;}/** * 对象查询 * @param <T> * @param beanClass * @param sql * @param params * @return */@SuppressWarnings("rawtypes")public static <T> List<T> query(Class<T> beanClass, String sql, Object...params) {try{return (List<T>)_g_runner.query(getConnection(), sql, _IsPrimitive(beanClass)?_g_columnListHandler:new BeanListHandler(beanClass), params);}catch(SQLException e){throw new DBException(e);}}/** * 支持缓存的对象查询 * @param <T> * @param beanClass * @param cache_region * @param key * @param sql * @param params * @return */public static <T> List<T> query_cache(Class<T> beanClass, String cache_region, Serializable key, String sql, Object...params) {List<T> objs = (List<T>)CacheManager.get(cache_region, key);if(objs == null){objs = query(beanClass, sql, params);CacheManager.set(cache_region, key, (Serializable)objs);}return objs;}/** * 分页查询 * @param <T> * @param beanClass * @param sql * @param page * @param count * @param params * @return */public static <T> List<T> query_slice(Class<T> beanClass, String sql, int page, int count, Object...params) {if(page < 0 || count < 0) throw new IllegalArgumentException("Illegal parameter of 'page' or 'count', Must be positive.");int from = (page - 1) * count;count = (count > 0) ? count : Integer.MAX_VALUE;return query(beanClass, sql + " LIMIT ?,?", ArrayUtils.addAll(params, new Integer[]{from,count}));}/** * 支持缓存的分页查询 * @param <T> * @param beanClass * @param cache * @param cache_key * @param cache_obj_count * @param sql * @param page * @param count * @param params * @return */public static <T> List<T> query_slice_cache(Class<T> beanClass, String cache, Serializable cache_key, int cache_obj_count, String sql, int page, int count, Object...params) {List<T> objs = (List<T>)CacheManager.get(cache, cache_key);if(objs == null) {objs = query_slice(beanClass, sql, 1, cache_obj_count, params);CacheManager.set(cache, cache_key, (Serializable)objs);}if(objs == null || objs.size()==0)return objs;int from = (page - 1) * count;if(from < 0)return null;if((from+count) > cache_obj_count)//超出缓存的范围return query_slice(beanClass, sql, page, count, params);int end = Math.min(from + count, objs.size());if(from >= end)return null;return objs.subList(from, end);}/** * 执行统计查询语句,语句的执行结果必须只返回一个数值 * @param sql * @param params * @return */public static long stat(String sql, Object...params) {try{Number num = (Number)_g_runner.query(getConnection(), sql, _g_scaleHandler, params);return (num!=null)?num.longValue():-1;}catch(SQLException e){throw new DBException(e);}}/** * 执行统计查询语句,语句的执行结果必须只返回一个数值 * @param cache_region * @param key * @param sql * @param params * @return */public static long stat_cache(String cache_region, Serializable key, String sql, Object...params) {Number value = (Number)CacheManager.get(cache_region, key);if(value == null){value = stat(sql, params);CacheManager.set(cache_region, key, value);}return value.longValue();}/** * 执行INSERT/UPDATE/DELETE语句 * @param sql * @param params * @return */public static int update(String sql, Object...params) {try{return _g_runner.update(getConnection(), sql, params);}catch(SQLException e){throw new DBException(e);}}/** * 批量执行指定的SQL语句 * @param sql * @param params * @return */public static int[] batch(String sql, Object[][] params) {try{return _g_runner.batch(getConnection(), sql, params);}catch(SQLException e){throw new DBException(e);}}}