这个示例通过一个spring mvc用户登录的示例来学习是如何进行spring web开发的。
业务功能:用户通过登录页面输入用户名和密码,提交验证,登录成功则更新用户登录信息(登录ip,最后访问时间,积分+5)同时记录用户登录成功日志。整个demo分为四层,每层对应一个对立的配置文件。
持久层对象,也是域对象也叫实体。
持久层:spring整合多种流行ORM框架,如hibernate,ibatis等,此demo采用spring JDBC,通过调用org.springframework.jdbc.core.JdbcTemplate完成DAO的实现。配置文件命名(app-dao.xml)
业务层:以接口的方式,调用持久层DAO。接口的方式可增加代码的灵活性,同时有利于项目的管理以及变更。配置文件命名(app-service.xml)
表现层:采用spring mvc框架。层次与struts类似,不过要手动配置Spring MVC地址映射,控制器,以及URL与控制器映射定义。个人认为初次配置觉得较struts而言麻烦点,但很灵活。可以通过配置手动配置请求地址,响应地址。关于整个demo将上传,下面解释下各配置文件。
1.在spring中装配DAO(这里以userlogin-dao.xml为例)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd" > <beans> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test"/> <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 id="userDao" class="com.me.dao.imp.UserDaoImp"> <property name="jdbcTemplate" ref="jdbcTemplate"/> </bean> <bean id="userLogDao" class="com.me.dao.imp.UserLogDaoImp"> <property name="jdbcTemplate" ref="jdbcTemplate"/> </bean> </beans>
这里主要想说的的是jdbcTemplate,因为此demo采用spring JDBC实现的持久层,而spring JdbcTemplate封装了jdbc的操作,本身只需要一个DataSource.
2.配置业务层(这里以userlog-service.xml为例)
...
<beans> <!--事务管理器:对目标类方法进行事务管理--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--需要代理哦业务目标类--> <bean id="userServiceTarget" class="com.me.service.imp.UserServiceImp"> <property name="userDao" ref="userDao"/> <property name="logDao" ref="userLogDao"></property> </bean> <!--配置声明式事务--> <bean id="userService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="transactionManager"></property> <property name="target" ref="userServiceTarget"/> <!--声明式事务的规则,属性、值--> <property name="transactionAttributes"> <props> <prop key="findUserByUserName"> PROPAGATION_REQUIRED,readOnly </prop> <prop key="checkUser">PROPAGATION_REQUIRED,readOnly</prop> <prop key="loginSuccess">PROPAGATION_REQUIRED</prop> </props> </property> </bean> </beans>
大家知道凡是操作数据库都要涉及到事务处理,而利用spring我们将不用在代码实现中担心这一点,通过spring声明式事务配置即可。这里需要额外提一下transactionAttributes是定义目标业务类那些方法需要业务的支持以及事务控制属性。PROPAGATION_REQUIED是用得最多的事务传播类型,表示业务方法在当前线程中查看是否有事务,如果有,就利用这个事务,否则就创建一个新事务。readOnly表示是只读事务,可以提高运行效率。此外,在配置方法名时,可实用“*”,不过不指定方法就表示对所有方法进行事务管理。
3.配置Spring MVC 框架
1)修改web.xml,以便web容器启动时自动启动Spring容器。
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:userlogin-dao.xml,classpath:userlog-service.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
2)配置spring mvc地址映射,与struts一样,spring mvc也需要一个servlet截获URL,修改web.xml.
<servlet> <servlet-name>userlogin</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>userlogin</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping>
需要说明的像struts一样,spring也需要一个类似struts-config.xml的配置文件,但命名可有讲究的哦,要采用<servlet-name>-servlet.xml以这个例子来说则需要在/WEB-INF目录下创建一个userlogin-servlet.xml,但这个配置文件无需在web.xml配置上下文参数,因为spring mvc的servlet会自动将userlogin-servlet.xml与spring其他配置文件(userlogin-dao.xml,userlog-service.xml)进行拼装。
3)在配置文件中声明控制器(userlogin-servlet.xml)
<beans> <bean name="loginController" class="com.me.web.LoginController"> <property name="userService" ref="userService"></property> </bean> <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/loginController.html">loginController</prop> </props> </property> </bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
这个配置说明/loginController.html的请求将交由loginController类处理,处理结果返回一个ModelandView("param1","param2",param3)对象,带有三个参数,分别表示重定向视图逻辑名,保存在request范围内的一个变量名,变量的值。而viewResolver中就是在配置重定向的页面,它的url是:prefix+parma1+suffix.此demo中登录成功后将重定向到{basepath}/jsp/main.jsp
最后处理下乱码问题。此demo采用的是uft-8的字符编码,后来还是出现了乱码,于是调用spring 中的过滤器进行过滤。修改web.xml.
<filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/jsp/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>*.html</url-pattern> </filter-mapping> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping>
初次接触spring mvc,还在学习。将上传此demo与大家分享、探讨。
package com.me.web;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
//import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.mvc.AbstractCommandController;
import com.me.entity.User;
import com.me.service.UserService;
import com.me.web.LoginCommand;
public class LoginController extends AbstractCommandController {
private UserService userService;
public LoginController(){
this.setCommandClass(LoginCommand.class);
}
@Override
protected ModelAndView handle(HttpServletRequest req,
HttpServletResponse res, Object command, BindException e)
throws Exception {
LoginCommand loginCommand = (LoginCommand)command;
System.out.print("username="+loginCommand.getUsername());
if(userService.checkUser(loginCommand.getUsername(),loginCommand.getPassword())){
User user = userService.findUserByUserName(loginCommand.getUsername());
user.setLastIP(req.getLocalAddr());
user.setLastVisit(new Date());
userService.loginSuccess(user);
req.getSession().setAttribute("user", user);
return new ModelAndView("main");
}else{
//用户不存在�û�������
return new ModelAndView("login","error","用户名或密码错误");
}
}
public void setUserService(UserService userService) {
this.userService = userService;
}
}
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib uri="/WEB-INF/c.tld" prefix="c"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Spring 鐧诲綍</title>
</head>
<body>
<br/>
<c:if test="${!empty error}">
<font color="red">${error}</font>
</c:if>
<form action="<c:url value="/loginController.html"/>" method="post">
鐢ㄦ埛鍚嶏細<input type="text" name="username" /><br/>
瀵? 鐮侊細<input type="password" name="password"/><br/>
<input type="submit" name="btn" value="鐧诲綍"/>
</form>
</body>
</html>
<%@ page language="java" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>鐧诲綍鎴愬姛</title>
</head>
<body>
鎭枩${user.username}鎴愬姛鐧诲綍锛屾偍鐜板湪鐨勭Н鍒嗘槸锛?{user.credits }
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd" >
<beans>
<bean name="loginController" class="com.me.web.LoginController">
<property name="userService" ref="userService"></property>
</bean>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/loginController.html">loginController</prop>
</props>
</property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>