背景介绍
最近刚做完毕业设计,打算把毕业设计的思路和中间碰到的问题在这里做一个记录,算是对近期的一个总结吧。
做的是JAVA WEB,因为之前实习做过,也是为了再熟练一下吧,毕竟这次是自己一个人的项目。
我选择了Spring MVC作为我的框架,也是因为相对用的比较熟吧。
先用一张图看看SpringMVC的流程:
Spring MVC采用了前端控制器的设计模式,即所有的请求都先被DispacherServlet拦截,然后再根据HandlerMapping中定义的映射关系分发到对应的Controller中。
Controller则是处理业务逻辑的地方,但实际开发中,Controller又会被分成Controller,Service和DAO层:Controller仅仅是用来接收参数,而Service才是处理业务逻辑的地方,即所谓的业务逻辑层。而DAO则是用来与数据库交互的。
Controller处理后返回一个ModelAndView对象,这个对象一般包含了视图名(Viewname)和模型数据(model,以Map的形式存储)。DispacherServlet会将viewname交给相应的ViewResolver来解析得到一个view对象,最后在将view对象和model渲染成为最终的view。其中从viewname解析成具体的view对象采用了策略模式,所以很容易替换视图解析器。也因为这样,才有了下面我们使用Velocity这个模板引擎来构造我们的页面。
由于之前在实习的公司用惯了XML配置文件的方式,所以这里还是采用了XML来配置bean以及bean之间的依赖关系。
本文首先介绍了如何在myeclipse下创建WEB工程并部署到tomcat上运行,然后再引入spring MVC框架并整合上iBATIS和Velocity,最后用一个小例子来演示了三者的集成工作。
新建WEB工程并部署到tomcat上运行
1、 在MyEclipse中新建一个web项目
2、 将默认的引入包删去以后,目录结构如下
3、配置tomcat,在windows-preference里搜索tomcat在tomcat6中配置好路径和jdk
5、把tomcat跑起来,键入http://localhost:8080/springVelocity/,success
引入Spring MVC并配置Velocity作为视图解析器
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/configuration/SpringMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
有几点需要注意一下:
①init-param中用来配置初始化参数,此处的contextConfigLocation设置的是配置文件的路径,这里我们的配置文件是/WEB-INF/configuration/SpringMVC.xml。默认DispatcherServlet会加载WEB-INF/[DispatcherServlet的名字]-servlet.xml配置文件
②*.do表示拦截任意以.do结尾的请求。
③load-on-startup表示此servlet在容器启动时初始化,数字代表初始化的顺序,数字越小初始化越早。
3、这样的话我们的Dispacher就可以拦截到所有以do结尾的请求了,然后我们需要将请求分发给相应的Controller,所以就要定义HandlerMapping啦,这个定义是在刚刚我们创建的springmvc配置文件中。
<!-- 控制器 -->
<bean id="testController" class="com.zhuchao.wmw.web.controller.TestController">
<property name="userService" ref="userService"></property>
</bean>
<!-- 请求映射 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/test.do">testController</prop>
</props>
</property>
</bean>
这里的HandlerMapping将/test.do的请求映射到testController上(这里的"/"就相当于我们的网址+/项目名称/),其实也就是DispatchServlet将请求分发给testController。testController可以来获得从request中传来的数据,交给service层处理,service层这里我们先不讲,就做一个简单的demo,业务也都写在controller里。
testController继承自AbstractController,AbstractController提供了一个空方法handleRequestInternal给我们,我们只需要重载这个方法就ok,当请求被DispatcherServlet转发到这个Controller的时候,就会调用handleRequestInternal,我们在这个方法里处理我们的业务逻辑然后返回一个ModelAndView。
<!-- velocity的配置 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="contentType" value="text/html;charset=utf-8" />
<property name="viewNames" value="*.htm,*.html,*.vm" />
</bean>
<bean id="velocityConfigurer" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<!-- resourceLoaderPath属性通知Velocity到哪里找到velocity模板 -->
<property name="resourceLoaderPath" value="/WEB-INF/views/"/>
<property name="velocityProperties">
<props>
<prop key="input.encoding">utf-8</prop>
<prop key="output.encoding">utf-8</prop>
</props>
</property>
</bean>
上面的配置有几点解释一下:一、Spring MVC会自动寻找实现ViewResolver接口的类并将它存入视图解析器列表,所以这里不需要手动注入。二、VelocityConfigurer也不用手动注入(it is not meant to be referenced by application components (just internally by VelocityView))。三、contentType就是配置模板html页面header标签里的contentType,后面的viewNames则是指需要模板引擎解析的模板文件(这里我们配置的是以htm、html或vm为后缀的文件)。四、resourceLoaderPath指定了velocity模板文件存放的路径。五、velocityProperties则是配置了velocity的一些相关属性。
5、以上就完成了Velocity的配置,现在只要把模板文件放到指定的路径下(/WEB-INF/views/),Velocity就可以帮助解析我们视图了。
如何将iBATIS整合进Spring呢?
1、 由于数据库我们用mysql,所以先要导入需要的包mysql-connector-java-5.1.26-bin.jar和ibatis-2.3.0.677.jar
2、 首先要定义数据源,这里我们使用spring提供的DriverManagerDataSource(实际项目中使用连接池)
导入spring-jdbc-3.2.0.M1.jar使用spring提供的DriverManagerDataSource获得dataSource
提供driverClassName,url,username,password等信息之后就配置好dataSource了
3、 接下来我们配置iBATIS:
Spring通过使用如下Bean集成iBATIS:SqlMapClientFactoryBean
其中有2个属性需要配置:
configLocations:用于指定SQL Map XML配置文件;
dataSource:用于定义数据源。
3.1 配置configLocations,即我们iBATIS的总配置文件
其中Settings元素用于优化SqlMapClient实例的各选项,具体参数配置可以参考这里http://blog.csdn.net/skey_chen/article/details/4644507
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<settings cacheModelsEnabled="true" enhancementEnabled="true"
lazyLoadingEnabled="true" maxRequests="32" maxSessions="10"
maxTransactions="5" useStatementNamespaces="true" />
<!-- 配置ibatis -->
<!-- 等生成了sqlMap文件再添加到此处-->
<!-- <sqlMap resource="com/zhuchao/wmw/dao/mapping/user_SqlMap.xml" /> -->
</sqlMapConfig>
3.2 配置dataSource
<!-- 数据源的定义 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/configuration/properties/dbConnectionForMysql.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driverClassName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
连接数据库的基本信息我们都放在了配置文件中(/WEB-INF/configuration/properties/dbConnectionForMysql.properties)4、 这里介绍一个工具:abator,用来自动生成实体类,对象关系映射(sqlMap),Example和DAO。
什么是Example:The example class can be used to generate a virtually unlimited where clauses。也就是用来动态生成sql的where条件的。
5、 具体的abator的用法:在myeclipse中加入abator的插件,然后新建一个abatorConfig.xml的页面然后补全???的部分就可以的,具体的可以参照我的项目中~
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE abatorConfiguration PUBLIC "-//Apache Software Foundation//DTD Abator for iBATIS Configuration 1.0//EN" "http://ibatis.apache.org/dtd/abator-config_1_0.dtd" >
<abatorConfiguration >
<abatorContext >
<!--数据库驱动以及一些连接信息-->
<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/wmw" userId="mysql" password="xxxxxx" >
<classPathEntry location="E:\8080\webapps\springVelocity\WEB-INF\lib\mysql-connector-java-5.1.26-bin.jar" />
</jdbcConnection>
<!--生成的model放在哪个项目的哪个包下-->
<javaModelGenerator targetPackage="com.zhuchao.wmw.dao.model" targetProject="springVelocity" />
<!--生成的sqlMap放在哪个项目的哪个包下-->
<sqlMapGenerator targetPackage="com.zhuchao.wmw.dao.mapping" targetProject="springVelocity"/>
<!--生成的dao放在哪个项目的哪个包下-->
<daoGenerator targetPackage="com.zhuchao.wmw.busi.dao" targetProject="springVelocity" type="GENERIC-CI" />
<table tableName="User">
</table>
</abatorContext>
</abatorConfiguration>
6、 现在我们有了model,mapping,dao和controller。我们可以把mapping添加到ibatis的总配置文件中去了,就像上图一样。现在我们就只差service了,我们再创建一层service就大功告成了,创建完成后目录结构如下:
7、 所有的类都写完了,接下来就是注入了,我们要把service的接口提供给controller,dao的接口提供给service(注意:都是接口),但是到注入的时候,才是具体的实现类。在层与层之间我们只需要知道接口的定义,调用接口即可完成所需要的逻辑单元应用,一切就非常清晰明了。
<!-- DAO层 -->
<bean id="userDAO" class="com.zhuchao.wmw.busi.dao.impl.UserDAOImpl">
<constructor-arg index="0" ref="sqlMapClient"></constructor-arg>
</bean>
<!-- 服务层 -->
<bean id="userService" class="com.zhuchao.wmw.busi.service.impl.UserServiceImpl">
<property name="userDAO" ref="userDAO"></property>
</bean>
<!-- 控制器 -->
<bean id="testController" class="com.zhuchao.wmw.web.controller.TestController">
<property name="userService" ref="userService"></property>
</bean>
接下来来具体实践一个小功能
需求:构建一个表单,实现这样一个功能:要求用户输入用户Id,然后单击确定,如果该用户存在,在下一个页面显示,HELLO,XXX,若不存在,则显示,Sorry。
1、首先构建页面(主要注意action="test.do",刚才在我们的handleMapping中已经配置好)
表单页面index.htm:
<html>
<head>
<title>Hello</title>
</head>
<body>
<h1>Hello</h1>
<form action="test.do" method="post">
Your name:<input type="text" name="username"/>
<input type="submit" value="submit">
</form>
</body>
</html>
反馈页面test2.htm:
<html>
<body>
<h1>$!info</h1>
</body>
</html>
2、在controller中我们可以接收到用户输入的id,然后通过Service层来处理具体的业务。
public class TestController extends AbstractController {
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
// 指定处理的视图名
ModelAndView mv = new ModelAndView("test2.htm");
String info = "Hello, ";
// 接收参数
String id = request.getParameter("username");
// 委托给service处理
User user = userService.getUserById(Integer.parseInt(id));
if (user != null) {
info = info + user.getName();
} else {
info = "Sorry, cannot be found";
}
mv.addObject("info", info);
return mv;
}
}
3、在userService接口中我们定义一个方法
public UsergetUserById(int id) throws SQLException;
4、在userServiceImpl中我们实现它
public User getUserById(int id) throws SQLException {
User user = new User();
user.setId(id);
return userDAO.selectByPrimaryKey(id);
}
大功告成,在index.htm中输入用户ID试试,看看是不是跳转到test2.htm并反馈了信息?