一、问题描述
最近把做的一个项目,整体升级了下,加入了一些SEO优化,其中SEO比较重要的就是URL伪静态,在网上搜了下,可以用URLRewrite实现伪静态。。。参考了以下几篇文章。。。
【1】https://blog.csdn.net/panda_52panda/article/details/76354619
【2】https://www.cnblogs.com/huiy/p/7816060.html
【3】https://www.cnblogs.com/zt19994/p/9477569.html
在本地采用【1】实现了效果,但是。。。我用的是jeesite4开发的,他打成的是war包,很尴尬的是,上传到服务器。。完全无效。。花了几个小时,看了下URLRewrite的源码。其中最主要的就是。。在UrlRewriteFilter中的loadUrlRewriterLocal方法。。该方法在本地调试时能成功的加载到文件,但是打成war包之后,发布到服务器上。。通过java -jar xxx.war的方式启动项目。。根本就获取不到文件。。
private void loadUrlRewriterLocal() {
InputStream inputStream = context.getResourceAsStream(confPath);
// attempt to retrieve from location other than local WEB-INF
if ( inputStream == null ) {
inputStream = ClassLoader.getSystemResourceAsStream(confPath);
}
URL confUrl = null;
try {
confUrl = context.getResource(confPath);
} catch (MalformedURLException e) {
log.debug(e);
}
String confUrlStr = null;
if (confUrl != null) {
confUrlStr = confUrl.toString();
}
if (inputStream == null) {
log.error("unable to find urlrewrite conf file at " + confPath);
// set the writer back to null
if (urlRewriter != null) {
log.error("unloading existing conf");
urlRewriter = null;
}
} else {
Conf conf = new Conf(context, inputStream, confPath, confUrlStr, modRewriteStyleConf);
checkConf(conf);
}
}
当看了其中的这个方法,就能理解【2】文章的做法。。我是spring boot开发的,所以本地用的是以下这种方式:
@Configuration
public class UrlRewriteFilterConfig{
@Bean
public FilterRegistrationBean urlRewrite(){
UrlRewriteFilter rewriteFilter = new UrlRewriteFilter();
FilterRegistrationBean registration = new FilterRegistrationBean(rewriteFilter);
registration.setUrlPatterns(Arrays.asList("/*"));
Map initParam = new HashMap();
initParam.put("confPath","urlrewirte.xml");
initParam.put("infoLevel","DEBUG");
registration.setInitParameters(initParam);
return registration;
}
}
原理:
在项目启动时,调用该方法初始化UrlRewriteFilter,UrlRewriteFilter是一个实现了Servlet的过滤器类。并传入一些参数,并将它注册到spring中,该方法执行完后,会调用UrlRewriteFilter中的init方法,在init方法中获取上面方面中传入的一些参数
public void init(final FilterConfig filterConfig) throws ServletException {
log.debug("filter init called");
if (filterConfig == null) {
log.error("unable to init filter as filter config is null");
return;
}
log.debug("init: calling destroy just in case we are being re-inited uncleanly");
destroyActual();
context = filterConfig.getServletContext();
if (context == null) {
log.error("unable to init as servlet context is null");
return;
}
// set the conf of the logger to make sure we get the messages in context log
Log.setConfiguration(filterConfig);
// get init paramerers from context web.xml file
String confReloadCheckIntervalStr = filterConfig.getInitParameter("confReloadCheckInterval");
String confPathStr = filterConfig.getInitParameter("confPath");
String statusPathConf = filterConfig.getInitParameter("statusPath");
String statusEnabledConf = filterConfig.getInitParameter("statusEnabled");
String statusEnabledOnHosts = filterConfig.getInitParameter("statusEnabledOnHosts");
String allowConfSwapViaHttpStr = filterConfig.getInitParameter("allowConfSwapViaHttp");
if (!StringUtils.isBlank(allowConfSwapViaHttpStr)) {
allowConfSwapViaHttp = "true".equalsIgnoreCase(allowConfSwapViaHttpStr);
}
// confReloadCheckInterval (default to null)
if (!StringUtils.isBlank(confReloadCheckIntervalStr)) {
// convert to millis
confReloadCheckInterval = 1000 * NumberUtils.stringToInt(confReloadCheckIntervalStr);
if (confReloadCheckInterval < 0) {
confReloadCheckEnabled = false;
log.info("conf reload check disabled");
} else if (confReloadCheckInterval == 0) {
confReloadCheckEnabled = true;
log.info("conf reload check performed each request");
} else {
confReloadCheckEnabled = true;
log.info("conf reload check set to " + confReloadCheckInterval / 1000 + "s");
}
} else {
confReloadCheckEnabled = false;
}
String modRewriteConf = filterConfig.getInitParameter("modRewriteConf");
if (!StringUtils.isBlank(modRewriteConf)) {
modRewriteStyleConf = "true".equals(StringUtils.trim(modRewriteConf).toLowerCase());
}
if (!StringUtils.isBlank(confPathStr)) {
confPath = StringUtils.trim(confPathStr);
} else {
confPath = modRewriteStyleConf ? DEFAULT_MOD_REWRITE_STYLE_CONF_PATH : DEFAULT_WEB_CONF_PATH;
}
log.debug("confPath set to " + confPath);
// status enabled (default true)
if (statusEnabledConf != null && !"".equals(statusEnabledConf)) {
log.debug("statusEnabledConf set to " + statusEnabledConf);
statusEnabled = "true".equals(statusEnabledConf.toLowerCase());
}
if (statusEnabled) {
// status path (default /rewrite-status)
if (statusPathConf != null && !"".equals(statusPathConf)) {
statusPath = statusPathConf.trim();
log.info("status display enabled, path set to " + statusPath);
}
} else {
log.info("status display disabled");
}
if (StringUtils.isBlank(statusEnabledOnHosts)) {
statusEnabledOnHosts = DEFAULT_STATUS_ENABLED_ON_HOSTS;
} else {
log.debug("statusEnabledOnHosts set to " + statusEnabledOnHosts);
}
statusServerNameMatcher = new ServerNameMatcher(statusEnabledOnHosts);
// now load conf from snippet in web.xml if modRewriteStyleConf is set
String modRewriteConfText = filterConfig.getInitParameter("modRewriteConfText");
if (!StringUtils.isBlank(modRewriteConfText)) {
ModRewriteConfLoader loader = new ModRewriteConfLoader();
Conf conf = new Conf();
loader.process(modRewriteConfText, conf);
conf.initialise();
checkConf(conf);
confLoadedFromFile = false;
} else {
loadUrlRewriter(filterConfig);
}
}
最终会调用loadUrlRewriter方法初始化文件。。
protected void loadUrlRewriter(FilterConfig filterConfig) throws ServletException {
try {
loadUrlRewriterLocal();
} catch(Throwable e) {
log.error(e);
throw new ServletException(e);
}
}
最终会初始化Conf类
private void loadUrlRewriterLocal() {
InputStream inputStream = context.getResourceAsStream(confPath);
// attempt to retrieve from location other than local WEB-INF
if ( inputStream == null ) {
inputStream = ClassLoader.getSystemResourceAsStream(confPath);
}
URL confUrl = null;
try {
confUrl = context.getResource(confPath);
} catch (MalformedURLException e) {
log.debug(e);
}
String confUrlStr = null;
if (confUrl != null) {
confUrlStr = confUrl.toString();
}
if (inputStream == null) {
log.error("unable to find urlrewrite conf file at " + confPath);
// set the writer back to null
if (urlRewriter != null) {
log.error("unloading existing conf");
urlRewriter = null;
}
} else {
Conf conf = new Conf(context, inputStream, confPath, confUrlStr, modRewriteStyleConf);
checkConf(conf);
}
}
Conf类就是【2】中用的一种方式初始化。。
@Configuration
public class UrlRewriteFilterConfig extends UrlRewriteFilter {
private static final String URL_REWRITE = "classpath:/urlrewrite.xml";
// Inject the Resource from the given location
@Value(URL_REWRITE)
private Resource resource;
// Override the loadUrlRewriter method, and write your own implementation
protected void loadUrlRewriter(FilterConfig filterConfig) throws ServletException {
try {
// Create a UrlRewrite Conf object with the injected resource
Conf conf = new Conf(filterConfig.getServletContext(), resource.getInputStream(), resource.getFilename(),
"@@traceability@@");
checkConf(conf);
} catch (IOException ex) {
throw new ServletException("Unable to load URL rewrite configuration file from " + URL_REWRITE, ex);
}
}
}
第【2】中方式,在我这边在使用的过程中,一直报错。。。resource一直获取不到,报空指针异常。。
二、解决方法
上面讲了一些,文件的初始过程,基本上能解决我遇到的问题,我这里最终的解决方法就是,将war包放到tomcat中运行,启动tomcat时会解压war,用于用的是web项目了。。所以改成了如下方式:
@Configuration
public class UrlWebRewriteFilterConfig extends UrlRewriteFilter {
@Override
protected void loadUrlRewriter(FilterConfig filterConfig) throws ServletException {
try {
Resource res = new ClassPathResource("urlrewirte.xml");
Conf conf = new Conf(filterConfig.getServletContext(), res.getInputStream(), res.getFilename(),
null);
checkConf(conf);
System.out.println("ok");
} catch (Exception ex) {
throw new ServletException("Unable to load URL rewrite configuration file from " + URL_REWRITE, ex);
}
}
}
通过spring-core核心包中的ClassPathResource来加载xml,因为我这边测试了几种常用的方式都获取为null。。。很尴尬
new ClassPathResource("urlrewirte.xml");
通过使用ClassPathResource成功的获取到了xml,然后就解决了这个问题。
urlrewirte.xml放在项目的resources目录下:
war包解压之后,urlrewirte.xml文件放在如下目录:
注意我这边针对的是jeesite4打包出来的war包,别的没有测试。