Posted By

oschina on 07/06/11


Tagged

url


Versions (?)

Custom url mapping: http://www.oschina.net/question/ask


 / Published in: Java
 

URL: http://www.oschina.net/code/snippet_12_2832

oschina 原来使用的是 servlet 对 url 进行映射,实现例如 http://www.oschina.net/project/tag/19/java 这样的URL地址。servlet 有很多不灵活的地方,现改成Filter的方式——URLMappingFilter。

  1. package net.oschina.servlets;
  2.  
  3. import java.io.*;
  4. import java.net.*;
  5. import java.util.*;
  6.  
  7. import javax.servlet.*;
  8. import javax.servlet.http.*;
  9.  
  10. import org.apache.commons.lang.StringUtils;
  11.  
  12. /**
  13.  * 此过滤器负责对编码进行自动处理,以及执行URL映射规则
  14.  * @author Winter Lau (http://www.oschina.net)
  15.  * @date 2011-1-10 下午02:20:49
  16.  */
  17. public class URLMappingFilter implements Filter {
  18.  
  19. private ServletContext context;
  20.  
  21. public final static String REQUEST_URI = "request_uri"; //{/index}
  22. private String PATH_PREFIX;
  23. private final static String VM_EXT = ".vm";
  24. private final static String VM_INDEX = "/index" + VM_EXT;
  25.  
  26. private String rootDomain = "oschina.net";
  27. private String default_base;
  28. private HashMap<String, String> other_base = new HashMap<String, String>();
  29. private List<String> ignoreURIs = new ArrayList<String>();
  30. private List<String> ignoreExts = new ArrayList<String>();
  31.  
  32. @Override
  33. public void init(FilterConfig cfg) throws ServletException {
  34. this.context = cfg.getServletContext();
  35.  
  36. //模板存放路径
  37. this.PATH_PREFIX = cfg.getInitParameter("template-path-prefix");
  38. if(this.PATH_PREFIX == null)
  39. this.PATH_PREFIX = "/WEB-INF/templates";
  40. else if(this.PATH_PREFIX.endsWith("/"))
  41. this.PATH_PREFIX = this.PATH_PREFIX.substring(0, this.PATH_PREFIX.length()-1);
  42.  
  43. //某些URL前缀不予处理(例如 /img/***)
  44. String ignores = cfg.getInitParameter("ignore");
  45. if(ignores != null)
  46. for(String ig : StringUtils.split(ignores, ','))
  47. ignoreURIs.add(ig.trim());
  48.  
  49. //某些URL扩展名不予处理(例如 *.jpg)
  50. ignores = cfg.getInitParameter("ignoreExts");
  51. if(ignores != null)
  52. for(String ig : StringUtils.split(ignores, ','))
  53. ignoreExts.add('.'+ig.trim());
  54.  
  55. //主域名,必须指定
  56. String tmp = cfg.getInitParameter("domain");
  57. if(StringUtils.isNotBlank(tmp))
  58. rootDomain = tmp;
  59.  
  60. //二级域名和对应页面模板路径
  61. @SuppressWarnings("unchecked")
  62. Enumeration<String> names = cfg.getInitParameterNames();
  63. while(names.hasMoreElements()){
  64. String name = names.nextElement();
  65. String v = cfg.getInitParameter(name);
  66. if(v.endsWith("/"))
  67. v = v.substring(0, v.length()-1);
  68. if("ignore".equalsIgnoreCase(name) || "ignoreExts".equalsIgnoreCase(name))
  69. continue;
  70. if("default".equalsIgnoreCase(name))
  71. default_base = PATH_PREFIX + v;
  72. else
  73. other_base.put(name, PATH_PREFIX + v);
  74. }
  75. }
  76.  
  77. @Override
  78. public void doFilter(ServletRequest req, ServletResponse res,
  79. FilterChain chain) throws IOException, ServletException {
  80. //自动编码处理
  81.  
  82. HttpServletRequest request = (HttpServletRequest)req;
  83. HttpServletResponse response = (HttpServletResponse)res;
  84. RequestContext rc = RequestContext.begin(this.context, request, response);
  85.  
  86. String req_uri = rc.uri();
  87.  
  88. try{
  89. //过滤URL前缀
  90. for(String ignoreURI : ignoreURIs){
  91. if(req_uri.startsWith(ignoreURI)){
  92. chain.doFilter(rc.request(), rc.response());
  93. return ;
  94. }
  95. }
  96. //过滤URL后缀
  97. for(String ignoreExt : ignoreExts){
  98. if(req_uri.endsWith(ignoreExt)){
  99. chain.doFilter(rc.request(), rc.response());
  100. return ;
  101. }
  102. }
  103.  
  104. rc.request().setAttribute(REQUEST_URI, req_uri);
  105. String[] paths = StringUtils.split(req_uri, '/');
  106. String vm = _GetTemplate(rc.request(), paths, paths.length);
  107.  
  108. rc.forward(vm);
  109.  
  110. } catch (SecurityException e){
  111. String login_page = e.getMessage() + "?goto_page=" + URLEncoder.encode(req_uri,"utf-8");
  112. rc.redirect(login_page);
  113. } finally {
  114. if(rc!=null) rc.end();
  115. }
  116. }
  117.  
  118. @Override
  119. public void destroy() {
  120. }
  121.  
  122. private String _GetTemplate(HttpServletRequest req, String[] paths, int idx_base) {
  123. StringBuilder vm = new StringBuilder(_GetTemplateBase(req));
  124.  
  125. if(idx_base == 0)
  126. return vm.toString() + VM_INDEX + _MakeQueryString(paths, idx_base);
  127.  
  128. for(int i=0;i<idx_base;i++){
  129. vm.append('/');
  130. vm.append(paths[i]);
  131. }
  132. String vms = vm.toString();
  133. String the_path = vms;
  134.  
  135. if(_IsVmExist(the_path + VM_EXT))
  136. return the_path + VM_EXT + _MakeQueryString(paths, idx_base);
  137.  
  138. the_path += VM_INDEX;
  139.  
  140. if(_IsVmExist(the_path))
  141. return the_path + _MakeQueryString(paths, idx_base);
  142.  
  143. vms += VM_EXT;
  144. if(_IsVmExist(vms))
  145. return vms + _MakeQueryString(paths, idx_base);
  146.  
  147. return _GetTemplate(req, paths, idx_base-1);
  148. }
  149.  
  150. private String _MakeQueryString(String[] paths, int idx_base) {
  151. StringBuilder params = new StringBuilder();
  152. int idx = 1;
  153. for(int i=idx_base;i<paths.length;i++){
  154. if(params.length()==0)
  155. params.append('?');
  156. if(i>idx_base)
  157. params.append('&');
  158. params.append("p");
  159. params.append(idx++);
  160. params.append('=');
  161. params.append(paths[i]);
  162. }
  163. return params.toString();
  164. }
  165.  
  166. private String _GetTemplateBase(HttpServletRequest req) {
  167. String base = null;
  168. String prefix = req.getServerName().toLowerCase();
  169. int idx = (rootDomain!=null)?prefix.indexOf(rootDomain):0;
  170. if(idx > 0){
  171. prefix = prefix.substring(0, idx - 1);
  172. base = other_base.get(prefix);
  173. }
  174. return (base==null)?default_base:base;
  175. }
  176.  
  177. private final static List<String> vm_cache = new Vector<String>();
  178.  
  179. /**
  180. * 判断某个页面是否存在,如果存在则缓存此结果
  181. * @param path
  182. * @return
  183. */
  184. private boolean _IsVmExist(String path){
  185. if(vm_cache.contains(path))
  186. return true;
  187. File testFile = new File(context.getRealPath(path));
  188. boolean isVM = testFile.exists() && testFile.isFile();
  189. if(isVM)
  190. vm_cache.add(path);
  191. return isVM;
  192. }
  193.  
  194. }

Report this snippet  

You need to login to post a comment.