今天好像大家来得都相当的晚……
=====================================================================
先把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的子节点,找到子节点之后,立刻
再去找这个子节点的子节点(典型的递归调用,没什么好说的)。