3月14日——培訓第79天

今天好像大家來得都相當的晚……

=====================================================================

先把Spring說完,然後是UML和設計模式,還有複習,最後應該是框架整合

Spring的表述層應用……

數據層應用是使用了模版的一種模式,通過Spring的jdbcTemplate讀取數據庫,通過模版調用回調
函數;LocalSessionFactoryBean得到Session,然後配合HibernateTemplate就可以……

與數據層類似,Spring不僅提供了具體的MVC實現,也給出了引入其它Web組件的接口。
由於具有天生的IOC和AOP特性,使得Spring的Web層應用輕巧而易於擴展。
即使是使用Struts等第三方框架,IOC和AOP特性也能很好地將它們融合進來。

Spring的MVC實現中,控制器也分爲總控制器和分控制器。
總控制器是DispatcherServlet,類似於Struts中ActionServlet。
分控制器是Controller,其處理請求的方法是handleRequest,類似於Struts中的Action
模型與視圖被定義成一個整體,在Spring中是使用ModelAndView表示的。

Struts中:
ActionServlet(總控制器)、RequestProcessor(模塊控制器)、Action(分控制器)三個控制器

嚴格來說,Struts中是沒有模型的,模型分邏輯模型和數據模型兩種………………

同樣的數據可以通過Spring的控制器生成pdf、excel、jsp等衆多視圖
------------------------------------------------------------------
SpringMVC大概流程:

符合配置要求的(比如.do結尾)請求來了之後,會被交給總控制器DispatcherServlet,
然後DispatcherServlet經過請求映射HandlerMapping來解析,解析後返回ModelAndView,
然後交給ViewResolver解析,最終生成視圖

配置DispatcherServlet-web.xml;(和Struts一樣也在web.xml中配置……)
定義Controller,返回模型與視圖;
配置Controller;
生成頁面,並訪問模型。

例子:
spring.jar加入到web工程的lib裏面去。

DispatcherServlet在org.springframework.web.servlet中

web.xml中配置
<servlet>
 <servlet-name>dispatcher</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

<servlet-mapping>
 <servlet-name>dispatcher</servlet-name>
 <url-pattern>*.htm</url-pattern>
</servlet-mapping>

這樣會給人一種假象,好像整個網站都是以.htm結尾的靜態網頁,其實是發送請求的動態網頁,所有擴展名
爲htm的網頁都會提交請求給總控制器,而html是靜態頁面

現在還需要分支控制器controller

import org.springframework.web.servlet.ModelAndView ;
import org.springframework.web.servlet.mvc.Controller ;
public class MyController implements Controller
{
 private String msg ;

 public void setMsg(String msg)
 {
  this.msg = msg ;
 }

 public ModelAndView handleRequest(HttpServletRequest request,
   HttpServletResponse response) throws Exception
 {
  return new ModelAndView("first.jsp","msg", msg) ;//ModelAndView返回給DispatcherServlet
              //會往請求作用域裏面存入這個msg,可以通過EL表達式
              //直接去取,比如${msg}
 }
}

ModelAndView是一個具體的類,裏面有setter方法,可以採用依賴注入的方式

比如first.jsp中可以有:
${msg}

新建一個dispatcher-servlet.xml
假如總控制器的名字是aaa,那麼這個xml文件的名字默認情況下應該是aaa-servlet.xml!
當然也可以通過別的方式改名

//用Spring的依賴注入,DOCTYPE的創建是參考bean.xml的
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
 "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>//注意這裏之所以不用id而用name是因爲id中是不可以有“/”的!
 <bean name="/first.htm" class="spring.MyController">
  <property name="msg" value="Hello,World" />
 </bean>
</beans>

總控制器叫DispatcherServlet、分支控制器是Controller、ModelAndView
解析出View

=====================================================================

把上面的例子稍微改一下,改成一個登錄的例子,應該把視圖和控制器隔離開來!

控制器:


import org.springframework.web.servlet.ModelAndView ;
import org.springframework.web.servlet.mvc.Controller ;
public class MyController implements Controller,ApplicationContextAware
{
 private String msg ; //模型信息
 private Properties targets ;//使用屬性類存儲success和failure兩個字符串……
 private JdbcTemplate template ;//需要依賴注入JdbcTemplate信息

 private ApplicationContext context ;

 public void setTemplate(JdbcTemplate template)
 {
  this.template = template ;
 }

 public void setTargets(Properties targets)
 {
  this.targets = targets ;
 }

 public void setMsg(String msg)
 {
  this.msg = msg ;
 }

 public ModelAndView handleRequest(HttpServletRequest request,
   HttpServletResponse response) throws Exception
 {
  String target = "success" ;
  Object[] args = {request.getParameter("username"),
    request.getParameter("password")} ;//從請求獲得用戶名和密碼!
  List result =
   template.queryForList("select * from users where username=? and password=?",args) ;

  if(result.isEmpty())
  {
   target = "failure" ;
  }

  return new ModelAndView(targets.getProperty(target),"msg",msg) ;
  //如果不需要返回模型信息的話,就不要後面兩個參數就可以了!
 }
}

bean.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
 "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
 
 //配置數據源:
 <bean id="dataSource"
  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  
  <property name="driverClassName" value="com.mysql.jdbc.Driver" />
  <property name="url" value="jdbc:mysql:///j2ee" />
  <property name="username" value="root" />
  <property name="password" value="root" />
 </bean>

 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  <property name="dataSource" ref="dataSource" />
 </bean>

 //配置控制器
 <bean name="/first.htm" class="spring.MyController">
  <property name="template" ref="jdbcTemplate"/>
  
  <property name="msg" value="Hello,World" />
  <property name="targets">
   <props>
    <prop key="success">/success.jsp</prop>
    <prop key="failure">/failure.jsp</prop>
   </props>
  </property>
 </bean>

</beans>

然後再創建出success.jsp和failure.jsp,就可以觀察結果了。

輸入網址,別忘了在地址中提供查詢字符串:
/first.htm?username=jsp&password=jsp

=======================================================================

注意上面兩個例子裏面都沒有提到HandlerMapping和ViewResolver以及View,其實不配置
前兩個,也會默認給你一個配置的,最後一個View也一樣,不管它的話也會有默認的設置。

這裏有一點需要注意!!

dispatcher-servlet.xml默認情況下是放在WEB-INF裏面的,但是以前裝載bean.xml的時候
是用XMLBeanFactory根據提供的路徑裝載的,但是這個despatcher-servlet.xml不在類路徑
裏面,沒辦法通過這種方式裝載,

現在如果我想給這個配置文件改名!並且我想把它放到classes目錄中去。

該怎麼做呢????

修改web.xml:

<servlet>
 <servlet-name>dispatcher</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 <init-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/classes/bean.xml</param-value>
 </init-param>
</servlet>

<servlet-mapping>
 <servlet-name>dispatcher</servlet-name>
 <url-pattern>*.htm</url-pattern>
</servlet-mapping>

==============================================================================

落了20分鐘的課程……
*.do給ActionServlet,然後根據模塊路徑轉到RequestProcessor,然後模塊控制器再根據
.do前面的名稱選擇適當的Action控制器

Spring的AOP可以對Struts進行更改,三種方式:
1、更改Action
2、在RequestProcessor去找Action之前加一道"屏障"
3、在ActionServlet去找RequestProcessor之前加一道“屏障”

比如說:http://localhost:8080/工程名/模塊名/*.do

例子:
將Struts整合進Spring中:

package cn.itcast ;

在struts-config中的最後加上:
其實在struts中的這個配置文件主要需要更改的第一是加上個plug-in,
第二是更改controller名稱,然後再依賴注入就成了。

<action-mappings>
 <action path="/list" type="cn.itcast.action.ListAction">
  <forward name="success" path="/list.jsp" />
 </action>
</action-mappings>

<controller
 processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>

<message-resources parameter="cn.itcast.ApplicationResources" />
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
 <set-property property="contextConfigLocation" value="/WEB-INF/bean.xml"/>
</plug-in>

這樣所有的請求就被轉到了Spring中,而不是Struts裏面,在Struts中根本感知不到Spring的存在
Spring和Struts按照如下方式集成的時候,根本就不需要怎麼更改Struts,只需要考慮Spring怎麼去
影響Struts的行爲就可以了。Spring使得程序鬆耦合,不至於表述層和數據層之間過分的依賴,而且
事務管理方面Spring也做的十分的不錯。

bean.xml中:

<beans>
 <bean name="/list" class="cn.itcast.action.ListAction">
  <property name="msg" value="hello!" />
 </bean>
</beans>

public class ListAction extends Action
{
 private String msg ;

//加入msg的setter方法
 
 public ActionForward execute()
 {
  request.setAttribute("msg",msg);
  return mapping.findForward("success");
 }
}


list.jsp:

${msg}

=========================================================

下面把Hibernate整合進來:

建立hibernate.cfg.xml

<session-factory>
 <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
 <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
 <property name="connection.url">jdbc:mysql///j2ee</property>
 <property name="connection.username">root</property>
 <property name="connection.password">root</property>
 <property name="show_sql">true</property>
</session-factory>


新建實體類:

package cn.itcast.vo;

public class Account
{
 private int id ;
 
 private balance ;

 //getter和setter方法
}

Account.hbm.xml:
<hibernate-mapping package="cn.itcast.vo">
 <class name="Account" table="accounts">
  <id name="id" column="id">
   <generator class="identity" />
  </id>
  <property name="balance" column="balance" />
 </class>
</hibernate-mapping>

bean.xml:
<beans>
 
 <bean id="sessionFactory"
  class="org.springframework.orm.hibernate3.localSessionFactoryBean">
  //加入Hibernate的兩個配置文件的位置
  <property name="configLocation" value="classpath:hibernate.cfg.xml" />
  <property name="mappingLocations">
   <list>
    <value>classpath:cn/itcast/vo/Account.hbm.xml</value>
   </list>
  </property>
 </bean>

 <bean id="hibernateTemplate"
  class="org.springframework.orm.hibernate3.HibernateTemplate">
  
  <property name="sessionFactory" ref="sessionFactory" />
 </bean>

 <bean name="/list" class="cn.itcast.action.ListAction">
  
  <property name="template" ref="hibernateTemplate" />
  <property name="className" value="cn.itcast.vo.Account" />
 </bean>
</beans>


public class ListAction extends Action
{
 private String className ;
 
 private HibernateTemplate template ;
//加入className和template的setter方法
 
 public ActionForward execute()
 {
  List list = template.find("from "+className) ;
  request.setAttribute("list",list);
  return mapping.findForward("success");
 }
}


//然後在list.jsp中迭代出來就成了。

<%@ taglib prefix="logic" uri="/WEB-INF/struts-logic.tld" %>

<table>
 <logic:iterate id="row" name="list">
  <tr>
   <td>${row.id}</td>
   <td>${row.balance}</td>
  </tr>
 </logic:iterate>
</table>

 

注意一個問題!!Hibernate的兩個配置文件的DOCTYPE一定要寫對,就是要以官方文檔爲準


---------------------------------------------------------------------

今天中午一點去面試了,也不知道對方的底細,當然也不知道自己的底細,糊里糊塗的就去了,
挺怪的,對方表現很沉穩,我也裝的很沉穩(其實我這個人骨子裏是很浮躁的,我一直是如此,
如果有人覺得我這個人踏實,那一定是誤會我了,有時我會裝的很踏實,就像今天面試的時候,
其實想想也知道,做it折行的,如果你很沉穩,你爲什麼來培訓呢?),雙方都沉穩,沉穩的
讓氣氛有些憋悶,那個地方挺漂亮,剛進門兩邊的牆上甚至寫滿了程序代碼!(不知是什麼語言,
反正不是C、C++或者java),二樓竟然有很多青年男女在踢毽子,一看就是個全是年輕人的地方,
面試的時候沒有問太多技術方面的細節問題(幾乎就沒怎麼問),主要問的是對某些東西的體會
或是感受,說白了就是處於優勢地位套你的話,探你的底,筆試題只有一道,我都懷疑我是否作對
了,因爲當時一看確實是太簡單了,就是一個樹的遞歸,真沒別的東西,當時不確定,回來寫了
一下子,其實看懂和寫明白確實差着距離,雖然寫出來了,但是還是不熟練……

package com.yuanbin.practice;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Demo {
 
 public static void generateTree(List list, int pid , int level)
 {
  StringBuffer title = new StringBuffer("") ;
  if( list != null && list.size() != 0)
  {
   Iterator it = list.iterator() ;   
   while(it.hasNext())
   {    
    Tree node = (Tree)it.next();//得到一個節點
    if(node.getPid()==pid)
    {
     String name = node.getName();//得到節點的名稱
     for(int i = 0 ; i < level ; i ++)
     {
      title.append("    ");
     }
     title.append(name);
     System.out.println(title.toString());
     title = new StringBuffer("");
     generateTree(list,node.getId(),level+1);
     
    }
   }
  }
  
 }
 public static void main(String[] args)
 {
  Tree tree1 = new Tree(0,1,"一級標題");
  Tree tree2 = new Tree(1,2,"二級標題");
  Tree tree3 = new Tree(2,3,"三級標題");
  Tree tree4 = new Tree(0,4,"一級標題");
  Tree tree5 = new Tree(3,5,"四級標題");
  Tree tree6 = new Tree(1,6,"二級標題");
  Tree tree7 = new Tree(1,7,"二級標題");
  Tree tree8 = new Tree(0,8,"一級標題");
  Tree tree9 = new Tree(2,9,"三級標題");
  
  Tree[] tree = {tree1,tree2,tree3,tree4,tree5,tree6,
    tree7,tree8,tree9};
  List list = new ArrayList();
  for(int i = 0 ; i < tree.length ; i ++)
  {
   list.add(tree[i]);
  }
  
  generateTree(list,0,0);
 }

事實證明,我沒有做錯,題目的意思就是讓你根據程序填空而已,沒什麼,代碼的意思
呢,也就是根據父id去遍歷子節點,作爲一級節點來說,父id是0(也就是沒有父id)
所以程序的入口點要從父id爲0開始,level級別是爲了表明各個節點名稱之前到底有
多少空格,每次找到一個節點之後,就立刻找這個id的子節點,找到子節點之後,立刻
再去找這個子節點的子節點(典型的遞歸調用,沒什麼好說的)。
 

發佈了111 篇原創文章 · 獲贊 6 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章