利用闲暇时间多刚刚结束的项目进行总结,这是一个普惠系统。支持业务员进件、审核、流转,同时支持管理员对员工、权限等进行管理。项目采用dubbo框架,前台用了freemarker+bootstrap。这里开始分析系统架构,从web.xml开始。
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Manage Serverdisplay-name>
<context-param>
<param-name>webAppRootKeyparam-name>
<param-value>Manage-Server.rootparam-value>
context-param>
<context-param>
<param-name>logbackConfigLocationparam-name>
<param-value>classpath:logback.xmlparam-value>
context-param>
<listener>
<listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListenerlistener-class>
listener>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>
classpath:spring/applicationContext-*.xml
classpath:spring/dubbo-consumer-parent.xml
param-value>
context-param>
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListenerlistener-class>
listener>
<listener>
<listener-class>
com.myph.manage.common.listener.CustomContextLoaderListener
listener-class>
listener>
<filter>
<filter-name>SetCharacterEncodingfilter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
filter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
<init-param>
<param-name>forceEncodingparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter>
<filter-name>shiroFilterfilter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>
<init-param>
<param-name>targetFilterLifecycleparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>SetCharacterEncodingfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<filter-mapping>
<filter-name>shiroFilterfilter-name>
<url-pattern>*.htmurl-pattern>
filter-mapping>
<filter>
<filter-name>sessionFilterfilter-name>
<filter-class>com.myph.common.filter.SessionFilterfilter-class>
<init-param>
<param-name>targetFilterLifecycleparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>sessionFilterfilter-name>
<url-pattern>*.htmurl-pattern>
filter-mapping>
<filter>
<filter-name>AntiXssFilterfilter-name>
<filter-class>com.myph.manage.common.util.AntiXssFilterfilter-class>
filter>
<filter-mapping>
<filter-name>AntiXssFilterfilter-name>
<url-pattern>*.jspurl-pattern>
<url-pattern>*.htmlurl-pattern>
<url-pattern>*.htmurl-pattern>
<url-pattern>/url-pattern>
<dispatcher>REQUESTdispatcher>
<dispatcher>FORWARDdispatcher>
<dispatcher>ERRORdispatcher>
<dispatcher>INCLUDEdispatcher>
filter-mapping>
<servlet>
<servlet-name>mvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>
classpath:spring/spring-app-mvc.xml
param-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>mvcservlet-name>
<url-pattern>*.htmurl-pattern>
servlet-mapping>
<session-config>
<session-timeout>420session-timeout>
session-config>
<welcome-file-list>
<welcome-file>login.htmwelcome-file>
welcome-file-list>
<error-page>
<error-code>404error-code>
<location>/error/404.htmllocation>
error-page>
<error-page>
<error-code>500error-code>
<location>/error/500.htmllocation>
error-page>
web-app>
web工程在启动时,会先读取web.xml配置文件中的配置,当这一步正确完成时,项目才能被正常启动起来。
1、启动项目时,首先会读取
节点和
节点。
2、创建一个ServletContext(servlet上下文),这个web项目的所有部分都共享这个上下文。
3、容器将
转换键值对,并交给servletContext。
4、容器将创建
中的类实例,创建监听。
web.xml中,各个元素的加载顺序是一定的,与各元素即使在文件中顺序无关。
servletContext–context-param–listener–filter–servlet。
需要注意的是,同一元素的加载是按顺序加载的,例如filter与filter-mapping,必须先定义filter,才能正确解析对应名字的filter-mapping。
web项目配置webAppRootKey 获得根目录。
Spring通过 org.springframework.web.util.WebAppRootListener 这个监听器来压入项目路径。但是如果在web.xml中已经配置了 ch.qos.logback.ext.spring.web.LogbackConfigListener这个监听器,则不需要配置WebAppRootListener了。因为Log4jConfigListener已经包含了WebAppRootListener的功能。
contextConfigLocation参数定义了需要装入spring的配置文件。
在服务器运行过程中,Spring不停的运行的计划任务和OpenSessionInViewFilter,使得Tomcat反复加载对象而产生框架并用时可能产生的内存泄漏,则使用IntrospectorCleanupListener作为相应的解决办法。
spring中的提供了一个名为org.springframework.web.util.IntrospectorCleanupListener的监听器。它主要负责处理由 JavaBeans Introspector的使用而引起的缓冲泄露。spring中对它的描述如下:它是一个在web应用关闭的时候,清除JavaBeans Introspector的监听器.web.xml中注册这个listener.可以保证在web 应用关闭的时候释放与掉这个web 应用相关的class loader 和由它管理的类如果你使用了JavaBeans Introspector来分析应用中的类,Introspector 缓冲中会保留这些类的引用.结果在你的应用关闭的时候,这些类以及web 应用相关的class loader没有被垃圾回收.不幸的是,清除Introspector的唯一方式是刷新整个缓冲.这是因为我们没法判断哪些是属于你的应用的引用.所以删除被缓冲的introspection会导致把这台电脑上的所有应用的introspection都删掉.需要注意的是,spring 托管的bean不需要使用这个监听器.因为spring它自己的introspection所使用的缓冲在分析完一个类之后会被马上从javaBeans Introspector缓冲中清除掉.应用程序中的类从来不直接使用JavaBeans Introspector.所以他们一般不会导致内部查看资源泄露.但是一些类库和框架往往会产生这个问题。
这是我们项目自己实现的监听,由于项目采用dubbo框架,dubbo默认使用log4j作为日志输出,而我们项目是采用logback来输出日志。
因此通过监听,设置切换成slf4j。
public class CustomContextLoaderListener extends ContextLoaderListener {
static{
//设置dubbo使用slf4j来记录日志
System.setProperty("dubbo.application.logger","slf4j");
}
}
这是spring MVC提供的字符集过滤器,防止乱码。
项目中用了shiro来管理权限,这里用了代理来注入spring bean,先filter中加入DelegatingFilterProxy类,”targetFilterLifecycle”指明作用于filter的所有生命周期。
原理是,DelegatingFilterProxy类是一个代理类,所有的请求都会首先发到这个filter代理,然后再按照”filter-name”委派到spring中的这个bean。
关于shiro,稍后再总结。
在Spring中配置的bean的name要和web.xml中的
一样,在项目中是这样配置的:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login.htm"/>
<property name="successUrl" value="/index.htm"/>
<property name="unauthorizedUrl" value="/unauthorized.htm"/>
<property name="filters">
<map>
<entry key="authc" value-ref="formAuthenticationFilter"/>
<entry key="concurrentlogin" value-ref="concurrentLoginControlFilter"/>
map>
property>
<property name="filterChainDefinitions">
<value>
/css/** = anon
/js/** = anon
/images/** = anon
/commom/** = anon
/unauthorized.htm = anon
/login.htm=anon
/sendLoginSmsCode.htm=anon
/dologin.htm=anon
/**/*.htm=authc,concurrentlogin
value>
property>
bean>
此外,spring bean实现了Filter接口,但默认情况下,是由spring容器来管理其生命周期的(不是由tomcat这种服务器容器来管理)。如果设置”targetFilterLifecycle”为True,则spring来管理Filter.init()和Filter.destroy();若为false,则这两个方法失效。
用于检查用户是否登录了系统,如果未登录,则重定向到指的登录页面。
http://blog.csdn.net/buster2014/article/details/42082141
这里看了这篇文章,觉得我们的这个过滤器没有起作用。
这是我们项目自己定义的校验html、sql特殊字符的过滤器。
核心代码:
/**
* 判断是否包含html特殊字符 getIncludeHtmlSpecialCharsFlag
*/
public static boolean getIncludeHtmlSpecialCharsFlag(String s) throws UnsupportedEncodingException {
boolean res = false;
s = replaceSpecialChars(s);
if ( // XSS黑名单
s.indexOf("javascript:") != -1 || s.indexOf("document.cookie") != -1 || s.indexOf("