各位看官,請做好心理準備,這個帖子會很長,因爲小弟已經做好寫很長的準備。
現在說一下需求,這次的項目是做一個水產養殖相關的項目,系統開啓以後很多地方要用到數據庫裏的字典數據,比如部門表,養殖對象表,這些數據是可變的,但是變化頻率很小,所有每次用到的時候都去數據庫取數據很明顯的是對資源的浪費,所以想按照以前的方法把數據從數據庫裏讀取出來,放到內存,每次用到的時候直接去內存找就可以了。想法應該是正確的,可是用到了SSH框架,做起來就有點小困難了,研究了一下午,總是是搞定。思路和代碼寫出來,有錯誤的地方請大家指正。
正式開始!中間的調錯過程省去,直接如何實現。
另配一個listener,和spring同時啓動,不可取。因爲listener的啓動機制貌似是線程,並不是按順序一個一個啓動,所有想到直接在spring的配置文件裏,註冊bean文件,讓bean文件來執行取數據的工作,但是這個bean顯然是不能使用DAO的類,因爲DAO層的東西無法注入進來,所以要有個替代的東西,這個東西好難找啊,就是BeanPostProcessor接口,用類PBSTrackManagerPostProcessor實現它其中的一個方法postProcessAfterInitialization,這個方法裏可以引入一個類GetDictionaryInfo,實現類的方法getAllInfo(),當getAllInfo去調用DAO層的數據時就可以了。
不說了,直接上源碼:
PBSTrackManagerPostProcessor.java
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @author ROC
* @2010年4月5日18:24:58
* 實現BeanPostProcessor接口,可以實現在Spring加載時,調取一個的對象的方法,使其能夠取得實例化以後的DAO.
*
*
*
* */
public class PBSTrackManagerPostProcessor implements BeanPostProcessor
{
public Object postProcessAfterInitialization(Object obj, String s)
throws BeansException
{
if(obj instanceof GetDictionaryInfo)//GetDictionaryInfo爲類名
{
((GetDictionaryInfo) obj).getAllInfo();//getAllInfo爲GetDictionaryInfo的方法
}
return obj;
}
public Object postProcessBeforeInitialization(Object obj, String s)
throws BeansException
{
return obj;
}
}
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @author ROC
* @2010年4月5日18:24:58
* 實現BeanPostProcessor接口,可以實現在Spring加載時,調取一個的對象的方法,使其能夠取得實例化以後的DAO.
*
*
*
* */
public class PBSTrackManagerPostProcessor implements BeanPostProcessor
{
public Object postProcessAfterInitialization(Object obj, String s)
throws BeansException
{
if(obj instanceof GetDictionaryInfo)//GetDictionaryInfo爲類名
{
((GetDictionaryInfo) obj).getAllInfo();//getAllInfo爲GetDictionaryInfo的方法
}
return obj;
}
public Object postProcessBeforeInitialization(Object obj, String s)
throws BeansException
{
return obj;
}
}
GetDictionaryInfo.java
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
import java.util.HashMap;
import javax.annotation.Resource;
import javax.servlet.ServletContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import java.util.ArrayList;
import edu.ldu.system.preferences.feeding.DAO.TdFeedingRatesDAO;
import edu.ldu.system.preferences.product.DAO.TdProductFishDAO;
/**
* @author ROC
* 2010年4月5日18:26:55
* 實現getAllInfo方法,取得所有常用字典表裏的數據
*
* */
public class GetDictionaryInfo {
@Resource
private TdFeedingRatesDAO tdFeedingRatesDAO ;
@Resource
private TdProductFishDAO tdProductFishDAO;
public GetDictionaryInfo(){
super();
}
private static WebApplicationContext springContext;
public static ServletContext _servletContext;//這個是爲了取servletContext
private static GetDictionaryInfo _instance;
public static GetDictionaryInfo getInstance()
{
springContext = WebApplicationContextUtils
.getWebApplicationContext(_servletContext);
if(null == _instance)
_instance = (GetDictionaryInfo)springContext.getBean("getDictionaryInfo");
return _instance;
}
public static HashMap<String,ArrayList> dictionaryInfoMap = new HashMap<String, ArrayList>();
public void getAllInfo() {
System.out.println("%%%%%%%%%%系統啓動加載......");
System.out.println("@@@@@@@@@@開始從數據庫中取數據!");
ArrayList tdFeedingRatesList = (ArrayList)tdFeedingRatesDAO.findAll();
System.out.println("數據LIST - 1 的大小 "+tdFeedingRatesList.size());
ArrayList tdProductFishList = (ArrayList)tdProductFishDAO.findAll();
System.out.println("數據LIST - 2 的大小 "+tdProductFishList.size());
System.out.println("@@@@@@@@@@數據從數據庫中全部取出!");
dictionaryInfoMap.put("tdFeedingRatesList", tdFeedingRatesList);
dictionaryInfoMap.put("tdProductFishList", tdProductFishList);
System.out.println("@@@@@@@@@@數據打包完畢,全部放進了dictionaryInfoMap!");
}
/**
* 重新加載字典表數據!
* */
public void reloadDictionaryInfoMap()
{
System.out.println("==========~~~~~~~~~~系統開始重新加載字典表");
dictionaryInfoMap.clear();
System.out.println("==========~~~~~~~~~~字典表MAP,清空成功!");
getAllInfo();
System.out.println("==========~~~~~~~~~~重新加載字典表成功");
}
public HashMap<String, ArrayList> getDictionaryInfoMap() {
return dictionaryInfoMap;
}
public void setDictionaryInfoMap(HashMap<String, ArrayList> dictionaryInfoMap) {
this.dictionaryInfoMap = dictionaryInfoMap;
}
}
import java.util.HashMap;
import javax.annotation.Resource;
import javax.servlet.ServletContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import java.util.ArrayList;
import edu.ldu.system.preferences.feeding.DAO.TdFeedingRatesDAO;
import edu.ldu.system.preferences.product.DAO.TdProductFishDAO;
/**
* @author ROC
* 2010年4月5日18:26:55
* 實現getAllInfo方法,取得所有常用字典表裏的數據
*
* */
public class GetDictionaryInfo {
@Resource
private TdFeedingRatesDAO tdFeedingRatesDAO ;
@Resource
private TdProductFishDAO tdProductFishDAO;
public GetDictionaryInfo(){
super();
}
private static WebApplicationContext springContext;
public static ServletContext _servletContext;//這個是爲了取servletContext
private static GetDictionaryInfo _instance;
public static GetDictionaryInfo getInstance()
{
springContext = WebApplicationContextUtils
.getWebApplicationContext(_servletContext);
if(null == _instance)
_instance = (GetDictionaryInfo)springContext.getBean("getDictionaryInfo");
return _instance;
}
public static HashMap<String,ArrayList> dictionaryInfoMap = new HashMap<String, ArrayList>();
public void getAllInfo() {
System.out.println("%%%%%%%%%%系統啓動加載......");
System.out.println("@@@@@@@@@@開始從數據庫中取數據!");
ArrayList tdFeedingRatesList = (ArrayList)tdFeedingRatesDAO.findAll();
System.out.println("數據LIST - 1 的大小 "+tdFeedingRatesList.size());
ArrayList tdProductFishList = (ArrayList)tdProductFishDAO.findAll();
System.out.println("數據LIST - 2 的大小 "+tdProductFishList.size());
System.out.println("@@@@@@@@@@數據從數據庫中全部取出!");
dictionaryInfoMap.put("tdFeedingRatesList", tdFeedingRatesList);
dictionaryInfoMap.put("tdProductFishList", tdProductFishList);
System.out.println("@@@@@@@@@@數據打包完畢,全部放進了dictionaryInfoMap!");
}
/**
* 重新加載字典表數據!
* */
public void reloadDictionaryInfoMap()
{
System.out.println("==========~~~~~~~~~~系統開始重新加載字典表");
dictionaryInfoMap.clear();
System.out.println("==========~~~~~~~~~~字典表MAP,清空成功!");
getAllInfo();
System.out.println("==========~~~~~~~~~~重新加載字典表成功");
}
public HashMap<String, ArrayList> getDictionaryInfoMap() {
return dictionaryInfoMap;
}
public void setDictionaryInfoMap(HashMap<String, ArrayList> dictionaryInfoMap) {
this.dictionaryInfoMap = dictionaryInfoMap;
}
}
然後這個GetDictionaryInfo.java是個普通的類,所有要有一個servlet啓動並且把取得HaspMap放到context裏去
MainServlet.java
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.ArrayList;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class MainServlet extends HttpServlet {
/**
* Initialization of the servlet. <br>
*
* @throws ServletException
* if an error occurs
*/
private static final long serialVersionUID = 1L;
// private SystemParamServicesImpl sysParamService;
private static WebApplicationContext springContext;
private ServletContext context;
public void init() throws ServletException {
// Put your code here
springContext = WebApplicationContextUtils
.getWebApplicationContext(this.getServletContext());
GetDictionaryInfo._servletContext=this.getServletContext();
context = this.getServletContext();
// GetDictionaryInfo getDictionaryInfo = new GetDictionaryInfo();
HashMap<String, ArrayList> dictionaryInfoMap = (HashMap<String, ArrayList>) GetDictionaryInfo.dictionaryInfoMap;
System.out.println("字典MAP裏的數據長度爲" + dictionaryInfoMap.size() + "個");
context.setAttribute("dictionaryInfoMap", dictionaryInfoMap);
System.out.println("@@@@@@@@@@系統字典表數據加載成功!");
}
/**
* Constructor of the object.
*/
public MainServlet() {
super();
}
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out
.println("<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML 4.01 Transitional//EN/">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(", using the GET method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to
* post.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out
.println("<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML 4.01 Transitional//EN/">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(", using the POST method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
}
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.ArrayList;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class MainServlet extends HttpServlet {
/**
* Initialization of the servlet. <br>
*
* @throws ServletException
* if an error occurs
*/
private static final long serialVersionUID = 1L;
// private SystemParamServicesImpl sysParamService;
private static WebApplicationContext springContext;
private ServletContext context;
public void init() throws ServletException {
// Put your code here
springContext = WebApplicationContextUtils
.getWebApplicationContext(this.getServletContext());
GetDictionaryInfo._servletContext=this.getServletContext();
context = this.getServletContext();
// GetDictionaryInfo getDictionaryInfo = new GetDictionaryInfo();
HashMap<String, ArrayList> dictionaryInfoMap = (HashMap<String, ArrayList>) GetDictionaryInfo.dictionaryInfoMap;
System.out.println("字典MAP裏的數據長度爲" + dictionaryInfoMap.size() + "個");
context.setAttribute("dictionaryInfoMap", dictionaryInfoMap);
System.out.println("@@@@@@@@@@系統字典表數據加載成功!");
}
/**
* Constructor of the object.
*/
public MainServlet() {
super();
}
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out
.println("<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML 4.01 Transitional//EN/">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(", using the GET method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to
* post.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out
.println("<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML 4.01 Transitional//EN/">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(", using the POST method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
}
然後完成註冊功能
applicationContext.XML
view plaincopy to clipboardprint?
<!-- 調用GetDictionaryInfo 讀的 -->
<bean id="pbsTrackManagerPostProcess" class="edu.ldu.utils.PBSTrackManagerPostProcessor" />
<bean id="getDictionaryInfo" class="edu.ldu.utils.GetDictionaryInfo" />
<!-- 調用GetDictionaryInfo 讀的 -->
<bean id="pbsTrackManagerPostProcess" class="edu.ldu.utils.PBSTrackManagerPostProcessor" />
<bean id="getDictionaryInfo" class="edu.ldu.utils.GetDictionaryInfo" />
配置web.xml讓MainServlet.java自啓動
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
<servlet>
<servlet-name>MainServlet</servlet-name>
<servlet-class>edu.ldu.utils.MainServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>MainServlet</servlet-name>
<servlet-class>edu.ldu.utils.MainServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
然後就是如何在Action裏取到數據了:
view plaincopy to clipboardprint?
ServletContext context = ServletActionContext.getServletContext();
HashMap dictionaryInfoMap = (HashMap)context.getAttribute("dictionaryInfoMap");
ServletContext context = ServletActionContext.getServletContext();
HashMap dictionaryInfoMap = (HashMap)context.getAttribute("dictionaryInfoMap");
又一個問題就是解決觸發一個函數,讓這些東西重新加載。
view plaincopy to clipboardprint?
GetDictionaryInfo.getInstance().reloadDictionaryInfoMap();
GetDictionaryInfo.getInstance().reloadDictionaryInfoMap();
reloadDictionaryInfoMap();實現起來時比較困難的,要在GetDictionaryInfo 取到ServletContext,而且要必須取到第一次實例的GetDictionaryInfo ,所有有一個東西很好用,就是Spring的context,取到他的方式
view plaincopy to clipboardprint?
private static WebApplicationContext springContext;
springContext = WebApplicationContextUtils
.getWebApplicationContext(_servletContext);
private static WebApplicationContext springContext;
springContext = WebApplicationContextUtils
.getWebApplicationContext(_servletContext);
這樣就大功告成,跑起來以後的結果,列出控制檯的輸出數據:
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
%%%%%%%%%%系統啓動加載......
@@@@@@@@@@開始從數據庫中取數據!
Hibernate: select tdfeedingr0_.pk_id as pk1_0_, tdfeedingr0_.fishTypeId as fishTypeId0_, tdfeedingr0_.waterTemperature as waterTem3_0_, tdfeedingr0_.growthStageId as growthSt4_0_, tdfeedingr0_.baitId as baitId0_, tdfeedingr0_.feedingRate as feedingR6_0_, tdfeedingr0_.state as state0_ from LDU_Aquaculture.dbo.td_feeding_rates tdfeedingr0_
數據LIST - 1 的大小 12
Hibernate: select tdproductf0_.pk_fishid as pk1_7_, tdproductf0_.fishname as fishname7_, tdproductf0_.fish_store as fish3_7_, tdproductf0_.state as state7_, tdproductf0_.creationDate as creation5_7_, tdproductf0_.lastModifiedDate as lastModi6_7_ from LDU_Aquaculture.dbo.td_product_fish tdproductf0_
數據LIST - 2 的大小 2
@@@@@@@@@@數據從數據庫中全部取出!
@@@@@@@@@@數據打包完畢,全部放進了dictionaryInfoMap!
字典MAP裏的數據長度爲2個
@@@@@@@@@@系統字典表數據加載成功!
系統啓動,開始裝載日誌文件……
DEBUG日誌文件路徑爲:E:/Program Files/Tomcat 6.0/webapps/Aquaculture/WEB-INF/logs/app-debug.log
INFO日誌文件路徑爲:E:/Program Files/Tomcat 6.0/webapps/Aquaculture/WEB-INF/logs/app-info.log
WARN日誌文件路徑爲:E:/Program Files/Tomcat 6.0/webapps/Aquaculture/WEB-INF/logs/app-warn.log
ERROR日誌文件路徑爲:E:/Program Files/Tomcat 6.0/webapps/Aquaculture/WEB-INF/logs/app-error.log
2010-4-6 9:35:38 org.apache.coyote.http11.Http11Protocol start
信息: Starting Coyote HTTP/1.1 on http-8080
2010-4-6 9:35:38 org.apache.jk.common.ChannelSocket init
信息: JK: ajp13 listening on /0.0.0.0:8009
2010-4-6 9:35:38 org.apache.jk.server.JkMain start
信息: Jk running ID=0 time=0/31 config=null
2010-4-6 9:35:38 org.apache.catalina.startup.Catalina start
信息: Server startup in 10921 ms
==========~~~~~~~~~~系統開始重新加載字典表
==========~~~~~~~~~~字典表MAP,清空成功!
%%%%%%%%%%系統啓動加載......
@@@@@@@@@@開始從數據庫中取數據!
Hibernate: select tdfeedingr0_.pk_id as pk1_0_, tdfeedingr0_.fishTypeId as fishTypeId0_, tdfeedingr0_.waterTemperature as waterTem3_0_, tdfeedingr0_.growthStageId as growthSt4_0_, tdfeedingr0_.baitId as baitId0_, tdfeedingr0_.feedingRate as feedingR6_0_, tdfeedingr0_.state as state0_ from LDU_Aquaculture.dbo.td_feeding_rates tdfeedingr0_
數據LIST - 1 的大小 12
Hibernate: select tdproductf0_.pk_fishid as pk1_7_, tdproductf0_.fishname as fishname7_, tdproductf0_.fish_store as fish3_7_, tdproductf0_.state as state7_, tdproductf0_.creationDate as creation5_7_, tdproductf0_.lastModifiedDate as lastModi6_7_ from LDU_Aquaculture.dbo.td_product_fish tdproductf0_
數據LIST - 2 的大小 2
@@@@@@@@@@數據從數據庫中全部取出!
@@@@@@@@@@數據打包完畢,全部放進了dictionaryInfoMap!
==========~~~~~~~~~~重新加載字典表成功
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/peng_wu01/archive/2010/04/06/5453361.aspx#