首页 > 程序开发 > 软件开发 > Java >

SpringMVC

2013-05-08

SpringMVC+SpringJDBC+SpringTransaction之前学习使用过Spring2.5以及和Hibernate和Struts2的集成,初步了解了Spring,业界对Spring的评价很高,我对其强大的功能只有蜻蜓点水般的体验,一直想学习接触一下Sprin...

SpringMVC+SpringJDBC+SpringTransaction


之前学习使用过Spring2.5以及和Hibernate和Struts2的集成,初步了解了Spring,业界对Spring的评价很高,我对其强大的功能只有蜻蜓点水般的体验,一直想学习接触一下Spring3.x,这会儿开始写了一个入门的SpringMVC+SpringJDBC和SpringTransaction的登陆案例,如同盲人摸象般地开始探索大象了。


至于Spring3的新特性,网上都有很多介绍,我看了,有很多东西没有实践过,所以一知半解,这里就不写了,那么就先找找感觉吧,开始我的编程之旅了...


看看我们的准备环境:
Spring3是基于JDK1.5的,对JDK1.6全面支持,所以编译Spring3.0必须使用JDK1.5以上,我用的是1.7版本的,数据库是MySQL5.0,开发工具是Meclipse8.5,。


1.工程名:spring3_learning,Jar包的准备:


这些jar包我都有上传,已经分类好了,可以直接去我的博客下载:http://download.csdn.net/detail/ysjian_pingcx/5335834


2.包结构的设计:


model包放的是与数据库有对应表的实体,vo包是一些Value Object用于辅助信息封装的,util放的是一些系统用到的工具类,controller放的是前段控制器
当模块多的时候,有必要在controller,dao,service,model前面加上模块名,便于管理和维护,此时可以讲util包加上system,
test是一个同等于src的目录,用于jUnit4测试的。


3.model的建立:
User:
[java] package com.meritit.ysjian.spring3learning.model;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable{
private static final long serialVersionUID = -5271584436847697641L;

private int userId;

private String userName;

private String password;

private int credits;

private String lastIp;

private Date lastVisit;

public String getLastIp() {
return lastIp;
}

public void setLastIp(String lastIp) {
this.lastIp = lastIp;
}

public Date getLastVisit() {
return lastVisit;
}

public void setLastVisit(Date lastVisit) {
this.lastVisit = lastVisit;
}

public int getUserId() {
return userId;
}

public void setUserId(int userId) {
this.userId = userId;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public int getCredits() {
return credits;
}

public void setCredits(int credits) {
this.credits = credits;
}

@Override
public String toString() {
return "User [credits=" + credits + ", lastIp=" + lastIp
+ ", lastVisit=" + lastVisit + ", password=" + password
+ ", userId=" + userId + ", userName=" + userName + "]";
}
}

package com.meritit.ysjian.spring3learning.model;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable{
private static final long serialVersionUID = -5271584436847697641L;

private int userId;

private String userName;

private String password;

private int credits;

private String lastIp;

private Date lastVisit;

public String getLastIp() {
return lastIp;
}

public void setLastIp(String lastIp) {
this.lastIp = lastIp;
}

public Date getLastVisit() {
return lastVisit;
}

public void setLastVisit(Date lastVisit) {
this.lastVisit = lastVisit;
}

public int getUserId() {
return userId;
}

public void setUserId(int userId) {
this.userId = userId;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public int getCredits() {
return credits;
}

public void setCredits(int credits) {
this.credits = credits;
}

@Override
public String toString() {
return "User [credits=" + credits + ", lastIp=" + lastIp
+ ", lastVisit=" + lastVisit + ", password=" + password
+ ", userId=" + userId + ", userName=" + userName + "]";
}
}LoginLog:
[java] package com.meritit.ysjian.spring3learning.model;
import java.io.Serializable;
import java.util.Date;

public class LoginLog implements Serializable{

private static final long serialVersionUID = -1764224611964600980L;

private int loginLogId;

private int userId;

private String ip;

private Date loginDate;

public String getIp() {
return ip;
}

public void setIp(String ip) {
this.ip = ip;
}

public Date getLoginDate() {
return loginDate;
}

public void setLoginDate(Date loginDate) {
this.loginDate = loginDate;
}

public int getLoginLogId() {
return loginLogId;
}

public void setLoginLogId(int loginLogId) {
this.loginLogId = loginLogId;
}

public int getUserId() {
return userId;
}

public void setUserId(int userId) {
this.userId = userId;
}

@Override
public String toString() {
return "LoginLog [ip=" + ip + ", loginDate=" + loginDate
+ ", loginLogId=" + loginLogId + ", userId=" + userId + "]";
}
}

package com.meritit.ysjian.spring3learning.model;
import java.io.Serializable;
import java.util.Date;

public class LoginLog implements Serializable{

private static final long serialVersionUID = -1764224611964600980L;

private int loginLogId;

private int userId;

private String ip;

private Date loginDate;

public String getIp() {
return ip;
}

public void setIp(String ip) {
this.ip = ip;
}

public Date getLoginDate() {
return loginDate;
}

public void setLoginDate(Date loginDate) {
this.loginDate = loginDate;
}

public int getLoginLogId() {
return loginLogId;
}

public void setLoginLogId(int loginLogId) {
this.loginLogId = loginLogId;
}

public int getUserId() {
return userId;
}

public void setUserId(int userId) {
this.userId = userId;
}

@Override
public String toString() {
return "LoginLog [ip=" + ip + ", loginDate=" + loginDate
+ ", loginLogId=" + loginLogId + ", userId=" + userId + "]";
}
}


4.接口的设计,Dao:
IUserDao:
[java] package com.meritit.ysjian.spring3learning.dao;

import com.meritit.ysjian.spring3learning.model.User;

public interface IUserDao {

/**
* 根据用户名和密码获取匹配的个数
* @param userName 用户名
* @param password 密码
* @return 返回匹配的个数
*/
public int getMatchCount(final String userName, final String password);

/**
* 根据用户名查找用户
* @param userName 用户名
* @return 返回用户对象
*/
public User findUserByUserName(final String userName);

/**
* 更新登陆信息
* @param user 登陆用户
*/
public void updateLoginInfo(User user);
}

package com.meritit.ysjian.spring3learning.dao;

import com.meritit.ysjian.spring3learning.model.User;

public interface IUserDao {

/**
* 根据用户名和密码获取匹配的个数
* @param userName 用户名
* @param password 密码
* @return 返回匹配的个数
*/
public int getMatchCount(final String userName, final String password);

/**
* 根据用户名查找用户
* @param userName 用户名
* @return 返回用户对象
*/
public User findUserByUserName(final String userName);

/**
* 更新登陆信息
* @param user 登陆用户
*/
public void updateLoginInfo(User user);
}UserDao:
[java] package com.meritit.ysjian.spring3learning.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Repository;

import com.meritit.ysjian.spring3learning.dao.IUserDao;
import com.meritit.ysjian.spring3learning.model.User;
import com.meritit.ysjian.spring3learning.util.EncryptUtils;

@Repository
// 注解Repository,告诉Spring这是一个仓库
public class UserDao implements IUserDao {

@Autowired
// 装配JdbcTemplate,JdbcTemplate在applicationContext.xml中配置了
private JdbcTemplate jdbcTemplate;

/**
* 根据用户名和密码获取匹配的个数
*
* @param userName
* 用户名
* @param password
* 密码
* @return 返回匹配的个数
*/
public int getMatchCount(final String userName, final String password) {
String sqlStr = " SELECT count(*) FROM tb_user "
+ " WHERE user_name =? and password=? ";
return jdbcTemplate.queryForInt(sqlStr, new Object[] { userName,
EncryptUtils.encryptByMD5(password) });
}

/**
* 根据用户名查找用户
*
* @param userName
* 用户名
* @return 返回用户对象
*/
public User findUserByUserName(final String userName) {
String sql = " SELECT user_id,user_name,credits "
+ " FROM tb_user WHERE user_name =? ";
final User user = new User();
jdbcTemplate.query(sql, new Object[] { userName },
new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
user.setUserId(rs.getInt("user_id"));
user.setUserName(userName);
user.setCredits(rs.getInt("credits"));
}
});
return user;
}

/**
* 更新登陆信息
*
* @param user
* 登陆用户
*/
public void updateLoginInfo(User user) {
String sql = " UPDATE tb_user SET last_visit=?,last_ip=?,credits=? "
+ " WHERE user_id =?";
jdbcTemplate.update(sql, new Object[] { user.getLastVisit(),
user.getLastIp(), user.getCredits(), user.getUserId() });
}
}

package com.meritit.ysjian.spring3learning.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Repository;

import com.meritit.ysjian.spring3learning.dao.IUserDao;
import com.meritit.ysjian.spring3learning.model.User;
import com.meritit.ysjian.spring3learning.util.EncryptUtils;

@Repository
// 注解Repository,告诉Spring这是一个仓库
public class UserDao implements IUserDao {

@Autowired
// 装配JdbcTemplate,JdbcTemplate在applicationContext.xml中配置了
private JdbcTemplate jdbcTemplate;

/**
* 根据用户名和密码获取匹配的个数
*
* @param userName
* 用户名
* @param password
* 密码
* @return 返回匹配的个数
*/
public int getMatchCount(final String userName, final String password) {
String sqlStr = " SELECT count(*) FROM tb_user "
+ " WHERE user_name =? and password=? ";
return jdbcTemplate.queryForInt(sqlStr, new Object[] { userName,
EncryptUtils.encryptByMD5(password) });
}

/**
* 根据用户名查找用户
*
* @param userName
* 用户名
* @return 返回用户对象
*/
public User findUserByUserName(final String userName) {
String sql = " SELECT user_id,user_name,credits "
+ " FROM tb_user WHERE user_name =? ";
final User user = new User();
jdbcTemplate.query(sql, new Object[] { userName },
new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
user.setUserId(rs.getInt("user_id"));
user.setUserName(userName);
user.setCredits(rs.getInt("credits"));
}
});
return user;
}

/**
* 更新登陆信息
*
* @param user
* 登陆用户
*/
public void updateLoginInfo(User user) {
String sql = " UPDATE tb_user SET last_visit=?,last_ip=?,credits=? "
+ " WHERE user_id =?";
jdbcTemplate.update(sql, new Object[] { user.getLastVisit(),
user.getLastIp(), user.getCredits(), user.getUserId() });
}
}@上面的findUserByUserName方法中用到了SpringJDBC的底层薄封装,jdbcTemplate.query(sql,new Object[]{userName},new RowCallbackHandler(){...})是一个匿名类实现的回调函数


ILoginLogDao:
[java] package com.meritit.ysjian.spring3learning.dao;

import com.meritit.ysjian.spring3learning.model.LoginLog;

public interface ILoginLogDao {

/**
* 记录日志
* @param loginLog 日志对象
*/
public void insertLoginLog(LoginLog loginLog);
}

package com.meritit.ysjian.spring3learning.dao;

import com.meritit.ysjian.spring3learning.model.LoginLog;

public interface ILoginLogDao {

/**
* 记录日志
* @param loginLog 日志对象
*/
public void insertLoginLog(LoginLog loginLog);
}LoginLog:
[java] package com.meritit.ysjian.spring3learning.dao.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.meritit.ysjian.spring3learning.dao.ILoginLogDao;
import com.meritit.ysjian.spring3learning.model.LoginLog;

@Repository
// 注解Repository,告诉Spring这是一个仓库
public class LoginLogDao implements ILoginLogDao {

@Autowired
// 装配JdbcTemplate,JdbcTemplate在applicationContext.xml中配置了
private JdbcTemplate jdbcTemplate;

/**
* 记录日志
*
* @param loginLog
* 日志对象
*/
public void insertLoginLog(LoginLog loginLog) {
String sql = "INSERT INTO tb_login_log(user_id,ip,login_datetime) "
+ "VALUES(?,?,?)";
Object[] args = { loginLog.getUserId(), loginLog.getIp(),
loginLog.getLoginDate() };
jdbcTemplate.update(sql, args);
}
}

package com.meritit.ysjian.spring3learning.dao.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.meritit.ysjian.spring3learning.dao.ILoginLogDao;
import com.meritit.ysjian.spring3learning.model.LoginLog;

@Repository
// 注解Repository,告诉Spring这是一个仓库
public class LoginLogDao implements ILoginLogDao {

@Autowired
// 装配JdbcTemplate,JdbcTemplate在applicationContext.xml中配置了
private JdbcTemplate jdbcTemplate;

/**
* 记录日志
*
* @param loginLog
* 日志对象
*/
public void insertLoginLog(LoginLog loginLog) {
String sql = "INSERT INTO tb_login_log(user_id,ip,login_datetime) "
+ "VALUES(?,?,?)";
Object[] args = { loginLog.getUserId(), loginLog.getIp(),
loginLog.getLoginDate() };
jdbcTemplate.update(sql, args);
}
}@注解Repository,告诉Spring这是一个仓库
@Autowired,装配JdbcTemplate,JdbcTemplate在applicationContext.xml中配置了

5.业务接口Service:
IUserService:
[java] package com.meritit.ysjian.spring3learning.service;

import com.meritit.ysjian.spring3learning.model.User;

public interface IUserService {

/**
* 判断是否有匹配的用户
* @param userName 用户名
* @param password 密码
* @return 返回boolean结果
*/
public boolean hasMatchUser(final String userName, final String password);

/**
* 根据用户名查找用户
* @param userName 用户名
* @return 返回用户对象
*/
public User findUserByUserName(final String userName);

/**
* 登陆成功,更新用户信息
* @param user 登陆用户
*/
public void loginSuccess(User user);
}

package com.meritit.ysjian.spring3learning.service;

import com.meritit.ysjian.spring3learning.model.User;

public interface IUserService {

/**
* 判断是否有匹配的用户
* @param userName 用户名
* @param password 密码
* @return 返回boolean结果
*/
public boolean hasMatchUser(final String userName, final String password);

/**
* 根据用户名查找用户
* @param userName 用户名
* @return 返回用户对象
*/
public User findUserByUserName(final String userName);

/**
* 登陆成功,更新用户信息
* @param user 登陆用户
*/
public void loginSuccess(User user);
}Uservice:
[java] package com.meritit.ysjian.spring3learning.service.impl;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.meritit.ysjian.spring3learning.dao.ILoginLogDao;
import com.meritit.ysjian.spring3learning.dao.IUserDao;
import com.meritit.ysjian.spring3learning.model.LoginLog;
import com.meritit.ysjian.spring3learning.model.User;
import com.meritit.ysjian.spring3learning.service.IUserService;

@Service
//注解Repository,告诉Spring这是一个Service
public class UserService implements IUserService{

@Autowired
private IUserDao userDao;
@Autowired
private ILoginLogDao loginLogDao;

/**
* 判断是否有匹配的用户
* @param userName 用户名
* @param password 密码
* @return 返回boolean结果
*/
public boolean hasMatchUser(final String userName, final String password) {
int matchCount =userDao.getMatchCount(userName, password);
return matchCount > 0;
}

/**
* 根据用户名查找用户
* @param userName 用户名
* @return 返回用户对象
*/
public User findUserByUserName(final String userName) {
return userDao.findUserByUserName(userName);
}

/**
* 登陆成功,更新用户信息
* @param user 登陆用户
*/
public void loginSuccess(User user) {
user.setCredits( 5 + user.getCredits());
LoginLog loginLog = new LoginLog();
loginLog.setUserId(user.getUserId());
loginLog.setIp(user.getLastIp());
loginLog.setLoginDate(user.getLastVisit());
userDao.updateLoginInfo(user);
loginLogDao.insertLoginLog(loginLog);
}
}

package com.meritit.ysjian.spring3learning.service.impl;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.meritit.ysjian.spring3learning.dao.ILoginLogDao;
import com.meritit.ysjian.spring3learning.dao.IUserDao;
import com.meritit.ysjian.spring3learning.model.LoginLog;
import com.meritit.ysjian.spring3learning.model.User;
import com.meritit.ysjian.spring3learning.service.IUserService;

@Service
//注解Repository,告诉Spring这是一个Service
public class UserService implements IUserService{

@Autowired
private IUserDao userDao;
@Autowired
private ILoginLogDao loginLogDao;

/**
* 判断是否有匹配的用户
* @param userName 用户名
* @param password 密码
* @return 返回boolean结果
*/
public boolean hasMatchUser(final String userName, final String password) {
int matchCount =userDao.getMatchCount(userName, password);
return matchCount > 0;
}

/**
* 根据用户名查找用户
* @param userName 用户名
* @return 返回用户对象
*/
public User findUserByUserName(final String userName) {
return userDao.findUserByUserName(userName);
}

/**
* 登陆成功,更新用户信息
* @param user 登陆用户
*/
public void loginSuccess(User user) {
user.setCredits( 5 + user.getCredits());
LoginLog loginLog = new LoginLog();
loginLog.setUserId(user.getUserId());
loginLog.setIp(user.getLastIp());
loginLog.setLoginDate(user.getLastVisit());
userDao.updateLoginInfo(user);
loginLogDao.insertLoginLog(loginLog);
}
}@注解Service,告诉Spring这是一个Service


6.applicationContext.xml:
上面的前提条件准备好了,此时相当于将要见的房子的原材料买好了,那么这些原材料怎么才能骑作用呢,比如@Autowired@Repository等这些注解怎么能生效呢,
这时就需要能够使用这些材料的设计师和建造师,看看Spring的核心配置文件,
[html] <?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

<!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 -->
<context:component-scan base-package="com.meritit.ysjian.spring3learning.dao" />
<context:component-scan base-package="com.meritit.ysjian.spring3learning.service" />

<!-- 用于直指定配置文件的位置信息,在dataSource中可以使用 -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:locations="classpath:jdbc.properties" />

<!-- 配置数据源,用了dbcp数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="${jdbc.driverClass}" p:url="${jdbc.url}"
p:username="${jdbc.userName}" p:password="${jdbc.password}" />

<!-- 配置Jdbc模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource" />

<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource" />

<!-- 通过AOP配置提供事务增强,让service包下所有Bean的所有方法拥有事务 -->
<aop:config proxy-target-class="true">
<aop:pointcut id="serviceMethods"
expression=" execution(* com.meritit.ysjian.spring3learning.service..*.*(..))" />
<aop:advisor pointcut-ref="serviceMethods" advice-ref="txAdvice" />
</aop:config>

<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
</beans>

<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

<!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 -->
<context:component-scan base-package="com.meritit.ysjian.spring3learning.dao" />
<context:component-scan base-package="com.meritit.ysjian.spring3learning.service" />

<!-- 用于直指定配置文件的位置信息,在dataSource中可以使用 -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:locations="classpath:jdbc.properties" />

<!-- 配置数据源,用了dbcp数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="${jdbc.driverClass}" p:url="${jdbc.url}"
p:username="${jdbc.userName}" p:password="${jdbc.password}" />

<!-- 配置Jdbc模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource" />

<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource" />

<!-- 通过AOP配置提供事务增强,让service包下所有Bean的所有方法拥有事务 -->
<aop:config proxy-target-class="true">
<aop:pointcut id="serviceMethods"
expression=" execution(* com.meritit.ysjian.spring3learning.service..*.*(..))" />
<aop:advisor pointcut-ref="serviceMethods" advice-ref="txAdvice" />
</aop:config>

<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
</beans>@<context:component-scan base-package="com.meritit.ysjian.spring3learning.dao" />和<context:component-scan base-package="com.meritit.ysjian.spring3learning.service" />
@其他的和Spring2.5中的配置差不多


7.web.xml的配置
既然是MVC,那么我们的核心控制器就需要在web.xml中配置:
[html] <?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<!-- 加载配置文件的路径信息 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>

<!-- SpringMVC的核心控制器 -->
<servlet>
<servlet-name>spring3</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>spring3</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
</web-app>

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<!-- 加载配置文件的路径信息 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>

<!-- SpringMVC的核心控制器 -->
<servlet>
<servlet-name>spring3</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>spring3</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
</web-app>
@这与Struts2中的核心控制器配置原理一样的。org.springframework.web.servlet.DispatcherServlet
@<url-pattern>*.html</url-pattern>这个可以手动指定,然后在jsp中与其一致就可以了。
@注意<servlet-name>spring3</servlet-name>,这个名字是spring3,后面用得到。


8.前端控制器Controller
核心控制器配置好了,看看前段控制器,也就是我们编写的普通的POJO,但很关键的地方在这:
LoginController:
[java] package com.meritit.ysjian.spring3learning.controller;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.meritit.ysjian.spring3learning.model.User;
import com.meritit.ysjian.spring3learning.service.IUserService;
import com.meritit.ysjian.spring3learning.vo.LoginParameters;

@Controller
// 注解Repository,告诉Spring这是一个Controller,即前端控制器
public class LoginController {

@Autowired
private IUserService userService;

@RequestMapping(value = "/index.html")
public String loginPage() {
return "login";
}

@RequestMapping(value = "/loginCheck.html")
public ModelAndView loginCheck(HttpServletRequest request,
LoginParameters loginParameters) {
boolean isValidUser = userService.hasMatchUser(loginParameters
.getUser().getUserName(), loginParameters.getUser()
.getPassword());
if (!isValidUser) {
return new ModelAndView("login", "error", "用户名或密码错误!");
// request.setAttribute("error", "用户名或密码错误!");
// return "login";
} else {
User user = userService.findUserByUserName(loginParameters
.getUser().getUserName());
user.setLastIp(request.getLocalAddr());
user.setLastVisit(new Date());
userService.loginSuccess(user);
request.getSession().setAttribute("user", user);
return new ModelAndView("main");
// return "main";
}
}
}

package com.meritit.ysjian.spring3learning.controller;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.meritit.ysjian.spring3learning.model.User;
import com.meritit.ysjian.spring3learning.service.IUserService;
import com.meritit.ysjian.spring3learning.vo.LoginParameters;

@Controller
// 注解Repository,告诉Spring这是一个Controller,即前端控制器
public class LoginController {

@Autowired
private IUserService userService;

@RequestMapping(value = "/index.html")
public String loginPage() {
return "login";
}

@RequestMapping(value = "/loginCheck.html")
public ModelAndView loginCheck(HttpServletRequest request,
LoginParameters loginParameters) {
boolean isValidUser = userService.hasMatchUser(loginParameters
.getUser().getUserName(), loginParameters.getUser()
.getPassword());
if (!isValidUser) {
return new ModelAndView("login", "error", "用户名或密码错误!");
// request.setAttribute("error", "用户名或密码错误!");
// return "login";
} else {
User user = userService.findUserByUserName(loginParameters
.getUser().getUserName());
user.setLastIp(request.getLocalAddr());
user.setLastVisit(new Date());
userService.loginSuccess(user);
request.getSession().setAttribute("user", user);
return new ModelAndView("main");
// return "main";
}
}
}@这个很关键了,@Controller注解告诉Spring这是一个控制器
@类似于Struts2中的Action类中方法名称,Spring3用@RequestMapping(value = "/loginCheck.html")指定方法如何映射请求路径
@请求return new ModelAndView("login", "error", "用户名或密码错误!");响应的方法可以返回一个ModelAndView对象,也可以是一个String,SpringMVC会自动解析并跳转目标页面。
@return new ModelAndView("login", "error", "用户名或密码错误!");,第一个参数为视图逻辑名,第二个参数为数据模型名称和数据模型对象,相当于request.setAttribute("error", "用户名或密码错误!");
@LoginParameters是vo包下的一个POJO:
[jav package com.meritit.ysjian.spring3learning.vo;

import com.meritit.ysjian.spring3learning.model.User;

/**
* @author PingCX
*
*/
public class LoginParameters {

private User user;

public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}

package com.meritit.ysjian.spring3learning.vo;

import com.meritit.ysjian.spring3learning.model.User;

/**
* @author PingCX
*
*/
public class LoginParameters {

private User user;

public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
9.SpringMVC的配置文件:
类似于Struts2中的struts.xml,前面配置Spring的核心过滤器的时候有个servlet-name节点的名称是spring3,这里的SpringMVC配置文件名命名为:spring3-servlet.xml
在WEB-INF目录下创建spring3-servlet.xml:
[html] <?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<!-- 扫描web包,应用Spring的注解 -->
<context:component-scan base-package="com.meritit.ysjian.spring3learning.controller"/>

<!-- 配置视图解析器,将ModelAndView及字符串解析为具体的页面 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/"
p:suffix=".jsp" />
</beans>

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<!-- 扫描web包,应用Spring的注解 -->
<context:component-scan base-package="com.meritit.ysjian.spring3learning.controller"/>

<!-- 配置视图解析器,将ModelAndView及字符串解析为具体的页面 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/"
p:suffix=".jsp" />
</beans>@<context:component-scan base-package="com.meritit.ysjian.spring3learning.controller"/>,寻找Controller的
@org.springframework.web.servlet.view.InternalResourceViewResolver和org.springframework.web.servlet.view.JstlView配置视图解析器,将ModelAndView或字符串解析为具体的页面
@p:prefix="/"指定前缀
@p:suffix=".jsp" />指定后缀,跳转至jsp页面

登陆login.jsp
搭建完毕,看看我们的login.jsp:
[html] <%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>登录</title>
</head>
<body>
<c:if test="${!empty error}">
<font color="red"><c:out value="${error}" /></font>
</c:if>
<form action="<c:url value="loginCheck.html"/>" method="post">
用户名:
<input type="text" name="user.userName">
<br>
密 码:
<input type="password" name="user.password">
<br>
<input type="submit" value="登录" />
<input type="reset" value="重置" />
</form>
</body>
</html>

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>登录</title>
</head>
<body>
<c:if test="${!empty error}">
<font color="red"><c:out value="${error}" /></font>
</c:if>
<form action="<c:url value="loginCheck.html"/>" method="post">
用户名:
<input type="text" name="user.userName">
<br>
密 码:
<input type="password" name="user.password">
<br>
<input type="submit" value="登录" />
<input type="reset" value="重置" />
</form>
</body>
</html>@<c:url value="loginCheck.html"/>,提交的请求,全路径,避免了绝对路径修改时发生找不到的问题
@ <font color="red"><c:out value="${error}" /></font>获取request空间中的额error消息


10.测试,jUnit:
[java] package com.meritit.ysjian.spring3learning.service;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)//这是基于junit4的Spring测试框架
@ContextConfiguration(locations={"/applicationContext.xml"})//加载配置文件
public class TestUserService {

@Autowired
private IUserService userService;

@Test
public void hasMatchUser(){
boolean result = userService.hasMatchUser("ysjian", "000");
assertTrue(result);
}
}

package com.meritit.ysjian.spring3learning.service;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)//这是基于junit4的Spring测试框架
@ContextConfiguration(locations={"/applicationContext.xml"})//加载配置文件
public class TestUserService {

@Autowired
private IUserService userService;

@Test
public void hasMatchUser(){
boolean result = userService.hasMatchUser("ysjian", "000");
assertTrue(result);
}
}
@上面是基于junit4的Spring测试,简单好用。


一个简单的SpringMVC+SpringJDBC+SpringTransaction的小应用实现了,后面再扩展模块的时候就在搭建好的地基上直接砌砖了,和SSH对比一下,有相似的地方,夸张点说Spring集大成于一身,值得挖掘,继续上路...


相关文章
最新文章
热点推荐