辭職待業青年就是有很多時間來寫博客,以前在傳統行業技術強度相對不大,不處理大數據,也不弄高並發的,所以學不到什么高端編程技術和架構方法,那么我自己就琢磨搞一個SSH架構的東西出來,希望可以幫助到一些朋友,也希望大拿給出相應的指導意見。
先從用了什么東西說起吧 SSHM=SpringMVC+Spring+Hibernate+Mybatis,至於為什么要這么搞,我先簡要的說下。
SpringMVC 我最初的想法就是,它比struts2小,屬於輕量級的MVC框架,而且和spring可以完美結合在一起。
Spring 額 不需要我廢話了。
hibernate 主要用來請求數據庫事物方面的應用,主要執行DML語句,不過用的比較挫,不太會,希望多指點。
Mybatis 主要用來查詢,因為查詢這個東西 我還是喜歡用SQL來查詢。
spring版本3.1.2,hibernate3,mybatis3.1.1 版本還是比較新的。其他的一些技術也包含進去了比如說poi,jdom,jackson等,就不一一介紹了。
這里插一段,在spring選擇版本初期,我是用的3.0.5這個版本,jackson 用的是一個比較低的版本,這兩個東西怎樣都不兼容,頭疼!在實驗了多個版本后,發現了jackson 這玩意向下不兼容,我去,有意思,最后確定了spring3.1.2往上與jackson2.1左右的版本才兼容,好吧,就當學習了。
先看下基礎web.xml配置吧
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" 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"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- spring 過濾器統一設置編碼 --> <filter> <filter-name>Spring character encoding filter</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>Spring character encoding filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 指定Spring Bean的配置文件所在目錄。默認配置在WEB-INF目錄下 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:config/applicationContext*.xml</param-value> </context-param> <!-- Web 項目 Spring 加載 Log4j 的監聽 --> <listener> <listener-class> org.springframework.web.util.Log4jConfigListener </listener-class> </listener> <!-- spring 應用上下文監聽器 主要初始化注入 --> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- Servlet模塊同時會加載{servletname}-servlet.xml文件 SpringMVC前值控制模式基礎selvlet --> <servlet> <servlet-name>newframe</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>newframe</servlet-name> <url-pattern>*.do</url-pattern><!-- 是攔截以.do結尾的請求,可自定義 --> </servlet-mapping> <!-- 如果不定義webAppRootKey參數,那么webAppRootKey就是缺省的"webapp.root"。 但最好設置,以免項目之間的名稱沖突。 定義以后,在Web Container啟動時將把ROOT的絕對路徑寫到系統變量里。 然后log4j的配置文件里就可以用${ myapp.root }來表示Web目錄的絕對路徑,把log文件存放於webapp中。 此參數用於后面的“Log4jConfigListener” --> <context-param> <param-name>webAppRootKey</param-name> <param-value>myapp.root</param-value> </context-param> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j.properties</param-value> </context-param> <session-config> <session-timeout>15</session-timeout> </session-config> </web-app>
每個標簽是不是都寫明白了呢?
那么我們從springMVC先開始介紹吧,我這里只講我怎樣搭建這個MVC的過程 至於SpringMVC的原理,我不想做過多的介紹,因為這不是本文的重點,並且也不是一句兩句話能說明白的,我看到有些文章 幾百字+幾張圖片就說這事springMVC的基本原理,我曾經略讀過一些springMVC的源碼,里面的復雜程度也不是簡單的幾句話能描述的清楚的,所以不做介紹,等小弟我真吃透了,在寫出來吧,有關資料可以參考spring官網對springMVC的介紹,不是很詳細,但是也能明白個大概。
不閑扯了,先看springMVC配置文件,位置:WEN-INF文件夾下,命名方式:以web.xml文件中DispatcherServlet的serlvletname-servlet.xml為公式命名,也可自定義文件名,在DispatcherServlet節點下加如下配置:
<init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/applicationContext-mvc.xml</param-value> </init-param>
MVC配置文件的內容如下:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 對web包中的所有類進行掃描,以完成Bean創建和自動依賴注入的功能 --> <mvc:annotation-driven></mvc:annotation-driven>
<!-- 先掃描controller 后service --> <context:component-scan base-package="com.tansun.newframe.*"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" /> </context:component-scan> <!-- 使注解生效 --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="mappingJacksonHttpMessageConverter" /> <bean class = "org.springframework.http.converter.StringHttpMessageConverter"> <property name = "supportedMediaTypes"> <list> <bean class="org.springframework.http.MediaType"> <constructor-arg index="0" value="text"/> <constructor-arg index="1" value="plain"/> <constructor-arg index="2" value="UTF-8"/> </bean> <bean class="org.springframework.http.MediaType"> <constructor-arg index="0" value="*"/> <constructor-arg index="1" value="*"/> <constructor-arg index="2" value="UTF-8"/> </bean> </list> </property> </bean> </list> </property> </bean> <!-- springmvc的配置文件,它的命名規則:web.xml里springmvc模塊的名稱+“-servlet.xml” 對模型視圖名稱的解析,即在模型視圖名稱添加前后綴 例如:Controller里返回一個名為test的邏輯視圖名稱,根據配置文件, 它最終找到的文件是/panges/test.jsp,即把前后綴拼裝為一個路徑。 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean> <!-- jaskson 用於前后台以json形式的數據交換,設置編碼集為utf-8編碼--> <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>application/json;charset=UTF-8</value> </list> </property> </bean> <!-- SpringMVC 異常處理機制 --> <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="java.lang.Exception">common/error</prop> <prop key="java.lang.Throwable">common/error</prop> </props> </property> <property name="statusCodes"> <props> <prop key="errors/500">500</prop> <prop key="errors/404">404</prop> </props> </property> <!-- 設置日志輸出級別,不定義則默認不輸出警告等錯誤日志信息 --> <property name="warnLogCategory" value="WARN"></property> <!-- 默認錯誤頁面,當找不到上面mappings中指定的異常對應視圖時,使用本默認配置 --> <property name="defaultErrorView" value="../error"></property> <!-- 默認HTTP狀態碼 --> <property name="defaultStatusCode" value="500"></property> </bean> </beans>
基於以上配置,springMVC的基礎配置應該算是完成了,簡單寫一個控制器。
@Controller 注解為此類為controller
@RequestMapping 注解類前,可以理解為請求URL的一個前置命名,在方法前可以理解為請求的后置命名,一下代碼的請求就是/newframe/test/getAllDemo.do
@Resource就不需要過多說明了吧,用過spring的人都知道是干啥的。
@Controller @RequestMapping(value="/test") public class DemoControl { @Resource(name="demoService") public DemoService cDemoService; @RequestMapping(value="/getAllDemo.do",method=RequestMethod.GET) public ModelAndView getAllDemo(){ ModelAndView tReturn = new ModelAndView("test/test_list"); List<Demo> mDemos =cDemoService.getAllDemo(); tReturn.addObject("demos", mDemos); return tReturn; } }
注意,返回值為一個ModelAndView對象,構造方法中傳入的“test/test_list”是一個JSP的路徑,在MVC的配置文件中已經簡單介紹過InternalResourceViewResolver這個就是他的應用,他表示執行完畢這個方法后轉發(注意是轉發)到/newframe/test/test_list.jsp,其中addObject方法設置一對鍵值,將這對鍵值設置到HttpRequest中(注意是request中)。如果直接返回"test/test_list"則InternalResourceViewResolver將字符串解析為jsp路徑也返回 到/newframe/test/test_list.jsp中。那么怎樣在這個方法中拿到request或者是response?其實我個人是不建議這么做的,因為如果使用request或者是response就又變成了J2EE編程了,失去了使用開源框架的意義,但是也有辦法
public ModelAndView getAllDemo(HttpRequest request,HttpResponse resopnse)
這樣就可以操作response,request了!
那么spring是如何與jackson相互配合使用的呢?
jackson是一個開源的 可以將JAVA實體對象轉換為JSON形式的數據格式的各種技術,他不需要你寫任何代碼(當然你也可以寫,但是比較麻煩,如果是想要自己用編程的方式來解決我建議可以用apache 的JSONArray,或者是Google的Gson兩種技術),只需要你配置到你的springMVC配置文件中,他可以將springMVC與前台的Javascript完美結合在一起,前台可以用jquery 來解析返回的json數據格式。具體配置方法上面已經給出,下面來介紹下controller中是如何應用的。
@RequestMapping(value = "/getUsers.do", method = RequestMethod.POST) @ResponseBody public Map<String, Object> getUsers(UserInfo userInfo, @RequestParam String page, @RequestParam String rows) throws Exception { // 獲得總條數 int totalNum = cUserInfoService.getUserCount(); // 獲得查詢到的用戶 List<UserInfoVo> userList = cUserInfoService.getUsers(userInfo, page, rows); Map<String, Object> mMap = new HashMap<String, Object>(); mMap.put("rows", userList); mMap.put("total", totalNum); return mMap; }
這里介紹一個注解@ResponseBody 他的作用是返回值JAVA對象(Obejct)將以響應體返回到前台頁面中,這里其實沒有response什么大事別理解錯了。
方法很簡單 將查詢到的用戶的List對象,和總條數返回到頁面中,將其封裝在一個map中了,哎,就這么簡單,這個Map在前台就以Json格式解析了。具體怎樣解析,那都是前端程序員的事情了,當然了,沒前端你就自己解析吧,很簡單的。
有些人就問了,你這個真是太麻煩了 如果我就返回兩個信息,難道也要封裝到Object中嗎?例如我返回給前台就{["result","1"],["msg","失敗!"]},難道我還需要封裝到一個對象中?其實編程是很靈活的,Spring的大牛們當然也考慮的這個問題。請參考一下方法!
/** * 用戶刪除方法 * * @param id * @return * @throws Exception */ @RequestMapping(value = "/userDelete.do", method = RequestMethod.POST) @ResponseBody public String userDelete(String ids) throws Exception { String mReturn = null; String mMsg = null; try { cUserInfoService.userInfoDelete(ids); mMsg = CodeTransferUtil.transferCode(DataConst.Del_Success); mReturn = JsonUtil.getJsonString(true, mMsg); } catch (SysContlException sException) { // 記錄日志 LogUtil.info(sException); // 編碼轉換 mMsg = CodeTransferUtil.transferCode(sException.getMessage()); // 處理 mReturn = JsonUtil.getJsonString(false, mMsg); } catch (DaoException dException) { // 記錄日志 LogUtil.info(dException); // 編碼轉換 mMsg = CodeTransferUtil.transferCode(dException.getMessage()); // 處理 mReturn = JsonUtil.getJsonString(false, mMsg); } catch (Exception e) { LogUtil.error(e); throw e; } return mReturn; }
這段代碼就返回了一個Json格式的字符串,那么@ResponseBody注解就將其返回一個字符串,具體spring內部是用StringHttpMessageConverter而非Jackson的
MappingJacksonHttpMessageConverter了,這樣字符串就會轉換為Json格式的數據返回給前台了。簡單的String,復雜的Object都有了明確的解決辦法,這樣就不會有問題了,這樣的應用基本上都是應用在與前台ajax技術相結合上。
這樣MVC部分就介紹完畢了,如果有任何問題歡迎留言,互相學習互相進步才是寫博客的關鍵,希望踴躍噴我~
