首页 > 代码库 > Spring实现登陆功能Demo

Spring实现登陆功能Demo

最近学习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=10000
4、在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=http://www.mamicode.com/"/login.do", method = RequestMethod.GET)>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=http://www.mamicode.com/"/profile.do",method = RequestMethod.GET)>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=http://www.mamicode.com/"${account.username}" />>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框架。


Spring实现登陆功能Demo