最近刚做完毕业设计,打算把毕业设计的思路和中间碰到的问题在这里做一个记录,算是对近期的一个总结吧。
做的是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,最后用一个小例子来演示了三者的集成工作。
1、 在MyEclipse中新建一个web项目
2、 将默认的引入包删去以后,目录结构如下
3、配置tomcat,在windows-preference里搜索tomcat在tomcat6中配置好路径和jdk
5、把tomcat跑起来,键入http://localhost:8080/springVelocity/,success
<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就可以帮助解析我们视图了。
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并反馈了信息?
需要源代码点击这里