3月14日——培训第79天

来源:互联网 发布:淘宝店费用一年多少钱 编辑:程序博客网 时间:2024/04/27 21:00

今天好像大家来得都相当的晚……

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

先把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的子节点,找到子节点之后,立刻
再去找这个子节点的子节点(典型的递归调用,没什么好说的)。
 

原创粉丝点击