最近学习SSH框架,看到Spring部分,下面通过实现一个登陆Demo来学习Spring的工作流程,配置,注解的使用等知识点。
1、在Eclipse下新建名为SpringDemo的Dynamic Web Project项目,导入spring相关jar包到lib目录下。
此外,项目还需导入aopallince、commons-logging、commons-dbcp、commons-collections、commons-pool等依赖jar包;
jsp页面使用了JSTL,因此需要在原lib基础上增加jstl.jar和standard.jar;数据库链接需mysql-connector-java包。
有时还需根据控制台的出错异常信息,导入缺少的jar包。
2、在web.xml下对Spring进行相关配置。
web.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>SpringDemo</display-name> <context-param> <param-name>webAppRootKey</param-name> <param-value>SpringDemo.webapp.root</param-value> </context-param> <!-- 指定log4j配置文件的位置 --> <!-- WebApplicationContext需要使用日志功能,放在Spring配置的前面 --> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j.xml</param-value> </context-param> <!-- --> <context-param> <param-name>log4fRefreshInterval</param-name> <param-value>60000</param-value> </context-param> <!-- 指定Spring配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <!-- 定义Web容器监听器,监听器负责完成IoC容器在Web环境中的启动工作 --> <!-- IoC容器启动过程就是建立上下文的过程 --> <!-- ContextLoaderListener启动的上下文为根上下文 --> <!-- ContextLoaderListener实现了ServletContextListener接口 --> <!-- ContextLoaderListener->ContextLoader:1,载入IoC容器到Web容器;2,实例化WebApplicationContext --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置log4j的监听器 --> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <!-- DispatcherServlet起着分发请求的作用,Spring MVC的核心 --> <!-- ContextLoaderListener初始化完成后,Web容器开始初始化DispatcherServlet --> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/dispatcherServlet.xml</param-value> </init-param> </servlet> <!-- 指定需要处理的http请求 --> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>3、在applicationContext.xml中配置Spring注解、数据库等信息
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 启动包扫描功能,将带有@Controller、@Service、@repository、@Component等注解的类
自动转化为成为spring的bean -->
<context:component-scan
base-package="com.demo.service" />
<context:component-scan
base-package="com.demo.dao" />
<!-- 数据源配置的文件,引入spring容器 -->
<context:property-placeholder
location="classpath:database.properties" />
<!-- dataSource,配置构建基于DBCP的数据源 -->
<bean
id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
lazy-init="false"
p:driverClassName="${dataSource.driverClassName}"
p:url="${dataSource.url}"
p:username="${dataSource.username}"
p:password="${dataSource.password}"
p:maxActive="${dataSource.maxActive}"
p:maxIdle="${dataSource.maxIdle}"
p:maxWait="${dataSource.maxWait}" />
<!-- 定义jdbcTemplate模版的Bean-->
<bean
class="org.springframework.jdbc.core.JdbcTemplate"<pre name="code" class="html">
p:dataSource-ref="dataSource" /> <!-- 事务管理配置 --> <beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"p:dataSource-ref="dataSource" /><tx:annotation-driventransaction-manager="transactionManager"
/> </beans>
其中引用的database.properties文件内容如下:
dataSource.driverClassName=com.mysql.jdbc.Driver dataSource.url=jdbc:mysql://localhost:3306/User dataSource.username=root dataSource.password=123456 dataSource.maxActive=200 dataSource.maxIdle=50 dataSource.maxWait=100004、在dispatcherServlet.xml中,配置控制层、AOP、视图解析等信息。
<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan
base-package="com.demo.controller" />
<bean
id="urlMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<!-- 对模型视图名称的解析,在请求时模型视图名称添加前后缀,将ModelAndView解析为具体页面 -->
<!-- 使用了JstlView作为视图解析器。同时,指定前缀路径为"/WEB-INF/jsp/",后缀路径为".jsp
Spring容器将会在这个路径中寻找匹配的jsp文件! -->
<bean id="jstlViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/views/"
p:suffix=".jsp" />
</beans>
“org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter”直接关系到多动作控制器配置是否可用!必须配置正确
5、新建Account实体类
package com.demo.domain;
import java.io.Serializable;
public class Account implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1862537539462186097L;
private Integer id;
private String username;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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 Account(){}
}
6、新建AccountDAO接口
package com.demo.dao;
import com.demo.domain.Account;
public interface AccountDao {
int getMatchCount(String username, String password);
Account getAcoountById(int id);
Account getAccountByName(String username);
}
7、新建AccountDaoImpl实现AccountDao接口,并配置@Repository注解,@Autowired注入jdbcTemplate用来访问数据库。
package com.demo.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.demo.dao.AccountDao;
import com.demo.domain.Account;
@Repository
public class AccountDaoImpl implements AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public int getMatchCount(String username, String password) {
String strSql = "select count(*) from user "
+ " where name = ? and password = ?";//?为参数占位符
return jdbcTemplate.queryForInt(strSql, new Object[]{ username, password});
}
@Override
public Account getAcoountById(int id) {
String strSql = "select id,name from user "
+ " where id = ?";
System.out.println("##########execute sql: "+strSql);
final Account account = new Account();
jdbcTemplate.query(strSql, new Object[]{ id },
//匿名方式实现的回调函数
new RowCallbackHandler(){
@Override
public void processRow(ResultSet rs) throws SQLException {
//将查询结果封装到对象实例中
account.setId(rs.getInt("id"));
account.setUsername(rs.getString("name"));
}
});
return account;
}
@Override
public Account getAccountByName(String username) {
String strSql = "select id,name from user "
+ " where name = ?";
System.out.println("##########execute sql: "+strSql);
final Account account = new Account();
jdbcTemplate.query(strSql, new Object[]{ username },
//匿名方式实现的回调函数
new RowCallbackHandler(){
@Override
public void processRow(ResultSet rs) throws SQLException {
//将查询结果封装到对象实例中
account.setId(rs.getInt("id"));
account.setUsername(rs.getString("name"));
}
});
return account;
}
}
8、新建AccountService接口。
package com.demo.service;
import com.demo.domain.Account;
public interface AccountService {
boolean hasMatchAccount(String username, String password);
Account getAccountById(int id);
Account getAccountByName(String username);
}
9、新建AccountServiceImpl类实现AccountService接口,并配置@Service注解,@Autowried注入AccountDao用来访问DAO
package com.demo.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.demo.dao.AccountDao;
import com.demo.domain.Account;
import com.demo.service.AccountService;
@Service
public class AccountServiceImpl implements AccountService{
@Autowired
private AccountDao accountDao;
@Override
public boolean hasMatchAccount(String username, String password) {
return accountDao.getMatchCount(username, password)>0;
}
@Override
public Account getAccountById(int id) {
return accountDao.getAcoountById(id);
}
@Override
public Account getAccountByName(String username) {
return accountDao.getAccountByName(username);
}
}
10、新建LoginController类,并配置@Controller注解,@Autowired注入AccountService;用来响应login请求。
package com.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.demo.domain.Account;
import com.demo.service.AccountService;
@Controller
public class LoginController {
@Autowired
private AccountService accountService;
/**
* init login form
* @param model
* @return
*/
@RequestMapping(value="/login.do", method = RequestMethod.GET)
public String initForm(ModelMap model){
System.out.println("########## init login page.");
Account account = new Account();
//绑定账户对象,也就是这个登录表单对象
model.addAttribute("account", account);
//指向登录页面
return "login";
}
/**
* login check
* @param user
* @return
*/
@RequestMapping(value="/loginCheck.do",method = RequestMethod.POST)
public String login(@ModelAttribute("user") Account account) {
Account account2 = accountService.getAccountByName(account.getUsername());
if (account2 != null) {
return "redirect:profile.do?id=" + account2.getId();
} else {
return "redirect:login.do";
}
}
}
11、新建AccountController类,并配置@Controller注解,@Autowired注入AccountService;用来响应profile请求。
package com.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.demo.domain.Account;
import com.demo.service.AccountService;
@Controller
public class AccountController {
@Autowired
private AccountService accountService;
/**
*
* @param id
* @param model
* @return
*/
@RequestMapping(value="/profile.do",method = RequestMethod.GET)
public String proflie(@RequestParam("id") int id, ModelMap model){
Account account = accountService.getAccountById(id);
model.addAttribute("account", account);
//跳转到用户信息界面
return "profile";
}
}
12、以上接口和类的结构图如下:
在上面的类中,都是用注解来进行配置。注解的确减少了代码的开发量,提高了效率。当然,这对于我们理解程序是一种挑战!如果你不知道原有的SpringMVC的流程,很难一开始就能摆弄清楚这些内容!
13、在WEB-INF目录下新建views文件夹,建立需要的jsp页面。
login.jsp内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/views/taglib.jsp"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login Page</title>
</head>
<body>
<fieldset><legend>登录</legend>
<form:form commandName="account" action="loginCheck.do" method="post">
<ul>
<li><form:label path="username">用户名:</form:label><form:input
path="username" /></li>
<li><form:label path="password">密码:</form:label><form:password
path="password" /></li>
<li>
<button type="submit">登录</button>
<button type="reset">重置</button>
</li>
</ul>
</form:form>
</fieldset>
</body>
</html>profile.jsp内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Profile Page</title>
</head>
<body>
<fieldset><legend>用户信息</legend>
<ul>
<li><label>用户名:</label><c:out value="${account.username}" /></li>
</ul>
</fieldset>
</body>
</html>taglib.jsp内容如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%> <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml"%> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>14、WEB-INF目录内容结构图如下:
15、整个项目Demo的编码工作基本就是这样。运行效果如下图:
登陆界面
用户信息界面:
16、总结:通过实现一个登陆Demo,学习了一下Spring框架的基本使用,项目比较简单,因此还有很多知识点未能涉及到。
Spring作为一个非常优秀的框架,可以号称“全栈框架”。
但是,从代码中依然可以看到Spring框架的不足。DAO层的数据库操作代码比较繁琐,而这里就有了ORM框架的用武之地。
Hibernate甚至连sql都不用写,就可实现常见的增删查改操作。
Spring作为一个开放性框架,能非常便捷的整合ORM框架。
原文地址:http://blog.csdn.net/dutsoft/article/details/41545091