【Spring+SpringMVC+Mybatis】利用SSM整合,完成用户登录、注册、修改密码系统

近年来,由于Struts2+Hibernate3+Spring3,这套SSH框架,Struts2屡次爆出安全漏洞,Hibernate就只会推行它HQL那套而越来越远离SQL查询关系数据库的本质,所以Spring+SpringMVC+Mybatis这套SSM框架悄然兴起,现阶段在Javaee领域,有种新项目必选SSM的趋势。本文将利用一个简单的例子,具体如下图所示,其实也就是把《【Struts2+Hibernate3+Spring3】利用SSH整合,完成打印用户表,用户登录、注册、修改密码系统》(点击打开链接)中的SSH例子再用SSM再做一次,同时视图尽可能地不杂糅其它技术,以最短的代码,给大家展示Spring、SpringMVC、Mybatis三者整合的例子。



一、SSM的下载和配置

在Eclipse新建一个JavaEE的Dynamic Web Project估计已经不用说了,接下来我就不用什么Maven了,自己配好所有必须的jar包,具体如下。

1、Spring和SpringMVC的下载和配置

其实Spring和SpringMVC所用的jar包都是相同的,毕竟Spring他希望自己一套吃遍Java的所有领域,但Spring做Java和xml交互、近年来SpringMVC做Java和JSP的交互做得最为突出,所以流行起来了。

Spring3.x的使用首先需要commons-logging-1.2.jar这玩意,这个commons-logging-1.2.jar是所有jar的前提,不然,你的java应用只有jar的话,spring根本启动不了,最直接的表现是配置了spring的javaee应用的tomcat启动不来。


所以,你要先下载commons-logging-1.2.jar。这玩意直接在Apache Tomcat的官网有,不是很明白为何不直接搞到Tomcat里面。

官网是:http://commons.apache.org/proper/commons-logging/download_logging.cgi


下载之后解压,直接取走里面的commons-logging-1.2.jar到你的java应用。

commons-logging-1.2-javadoc.jar是个API说明文档,并没有什么卵用。


接下来,才是下载Spring3.x。Spring的包全部放到http://repo.spring.io/里面了,在Spring的官网,http://spring.io你只会看到你并希望Maven下载和一大堆说明文档,顶多是最新版Github托管而已。

进入了spring的资源库之后,如下图,找到libs-release-local(这spring都不知道怎么想的,堂堂的javaee大厂,资源库里面的东西竟然不是按a-z排的)->org->springframework->spring->3.2.18 release然后选择右上角的download,下载Spring3.x的最终稳定版。


下载之后解压,在libs中,取走所有最终应用,关于API说明*-javadoc.jar、源代码*-sources.jar完全可以不需要。

2、JDBC和Mybatis的下载

JDBC请选择合适自己数据库的版本,本文用Mysql做例子,所以选择的是Mysql的JDBC。

你首先需要两个jar,一个是连接Mysql必须的jar,这里以Mysql做例子,Orcale等数据库则换成相应的jar包即可,可以到Mysql的官网下载:https://dev.mysql.com/downloads/connector/j/,下载之后取走其中的mysql-connector-java-5.1.44-bin.jar到你的工程目录,一般在工程目录新建一个lib,放这些包。


然后下载Mybatis,最新的Mybatis是放在Github托管的,网址:https://github.com/mybatis/mybatis-3/releases,同样取走里面的核心jar,放到你的工程目录的WEB-INF\lib下。


3、Mybatis和Spring交互包

最后补上这个jar就OK了。

还需要在https://github.com/mybatis/spring/releases下载一个Spring连接Mybatis的jar包mybatis-spring-1.3.1.jar:


整合之后WEB-INF\lib文件夹如下所示:



二、目录结构和所使用的数据库表

按照上述过程配好在WEB-INF\lib配好jar包之后,先贴上我最终完工的工程目录结构:


还有我使用的数据库表,还是这张早已举个栗子举烂的Mysql中test数据库的User用户表,随便开个Mysql,建立张user表,数据库test弄出来的。


三、配置文件xml的编写

1、我们先从这个Javaee工程的总配置文件web.xml看起,所有Javaee工程必有这个文件。在这个文件中,主要是声明使用SpringMVC、Spring还有这个网站主要使用UTF-8编码,避免乱码。

<?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"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	version="3.0">
	<!-- 启用SpringMVC -->
	<servlet>
		<servlet-name>SpringMVC</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>SpringMVC</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<!-- 指明Spring配置的初始化文件 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/applicationContext.xml</param-value>
	</context-param>
	<!-- 字符编码过滤器 -->
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/</url-pattern>
	</filter-mapping>
</web-app>

这里的web.xml的初始化,不同于之前《【Spring+Mybatis】Spring整合Mybatis》(点击打开链接)中,指明在 Java工程Spring的核心配置文件applicationContext.xml所在目录时,在contextConfigLocation的值只写一个applicationContext.xml就行,必须写明/WEB-INF/applicationContext.xml,不完全写明,Javaee工程找applicationContext.xml会直接去网站根目录WebContent找,肯定找不到,同时会出现org.springframework.beans.factory.BeanCreationException之类的错误

2、接下来先看SpringMVC-servlet.xml,命名只能这样写,毕竟在web.xml,指明的servlet-name就是SpringMVC,这个文件我在《【SpringMVC】Helloworld》( 点击打开链接)已经详细写过了,还是那句话,这篇文章主要是介绍SSM整合的,要是每个技术都写一次,就显得没有重点了。

这里除了要求SpringMVC在actios找servlet以外,同时要求Spring扫描Service层,是因为在action用到Service的类中的方法和数据库打交道,所以必须要求actions层注入Service。同时扫描test.actions和test.services。

<?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:mvc="http://www.springframework.org/schema/mvc"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd    
    http://www.springframework.org/schema/context     
    http://www.springframework.org/schema/context/spring-context-2.5.xsd    
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
  
    <context:component-scan base-package="test.actions" />  
    <context:component-scan base-package="test.services" />  
  
    <bean  
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
        <property name="prefix" value="/views/" />  
        <property name="suffix" value=".jsp" />  
    </bean>  
  
</beans>  

3、然后是Spring的核心配置文件applicationContext.xml了,这里和《【Spring+Mybatis】Spring整合Mybatis》( 点击打开链接)同样,同时整合JDBC和Mybatis,利用Spring配置数据源,同时指出Mybatis的核心配置文件是/WEB-INF/configuration.xml。这里还利用到Spring整合SpringMVC的自动注解功能,可以用一个@将原来的Spring必须要求的private私有变量+getter+setter,精简到一个注解+private私有变量即可。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-4.1.xsd ">
	<!-- Spring连接的JDBC数据源 -->
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url"
			value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useOldAliasMetadataBehavior=true" />
		<property name="username" value="root" />
		<property name="password" value="root" />
	</bean>
	<!-- 指出Mybatis的核心配置文件,关于数据库表和Java文件的映射写在里面 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="/WEB-INF/configuration.xml"></property>
	</bean>
	<!-- 指出数据库接口方法所在的包 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
		autowire="byName">
		<property name="basePackage" value="test.dao" />
		<property name="sqlSessionFactory" ref="sqlSessionFactory" />
	</bean>
	<!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
	<bean
		class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
</beans> 

这里/WEB-INF/configuration.xml也必须完全写明,不能只写configuration.xml,不然就会出现org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.mybatis.spring.mapper.MapperScannerConfigurer#0' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot resolve reference to bean 'sqlSessionFactory' while setting bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/configuration.xml]的报错,无法启动tomcat,具体如下图所示:

4、最后就是Mybatis的配置文件configuration.xml了,由于Spring的存在,让configuration.xml可以变得非常简单,不用像《【Mybatis】Helloworld》(点击打开链接)里面写得这么长,指出数据库和Java的映射关系Mapper的所在地即可。

<?xml version="1.0" encoding="UTF-8"?>    
<!DOCTYPE configuration      
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"      
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- 指明在user这个表中所包含常用sql方法,test/mapper/User.xml是一个指明java方法和sql语法联系的xml文件 -->
	<mappers>
		<mapper resource="test/mapper/User.xml" />
	</mappers>
</configuration>   

然后顺手在test.mapper包下新建一个User.xml。


四、工程核心文件的编写

经历了上面一大堆配置文件终于弄好整个Spring+SpringMVC+Mybatis的配置了,接下来开始分门别类地分层严格遵循MVC的思想编写整个Javaee工程的核心文件了。

1、首先完成刚才顺手建立的test.mapper.User.xml。该文件在《【Mybatis】Helloworld》(点击打开链接)详细说过了。主要是写关于该User表的主要操作和test.dao下的Java方法对应关系。这里分别有按照username查用户、增加一个用户、修改用户名对应密码的三个方法,也刚好展示Mybatis的增删改查了。

<?xml version="1.0" encoding="UTF-8" ?>   
<!DOCTYPE mapper PUBLIC    
    "-//mybatis.org//DTD Mapper 3.0//EN"   
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test.dao.UserDao">
	<select id="findUsersByUsername" resultType="test.entity.User">
		select * from user
		where username=#{username}
	</select>
	<!--执行增加操作的SQL语句。id和parameterType分别与IUserOperation接口中的addUser方法的名字和参数类型一致。 
		useGeneratedKeys设置为"true"表明要MyBatis获取由数据库自动生成的主键; keyProperty="id"指定把获取到的主键值注入到User的id属性 -->
	<insert id="addUser" parameterType="test.entity.User"
		useGeneratedKeys="true" keyProperty="id">
		insert into
		user(username,password) values(#{username},#{password})
	</insert>
	<update id="modifyPasswordByUsername" parameterType="test.entity.User">
		update user set password=#{password} where username=#{username}
	</update>
</mapper> 

2、然后马上来完成test.mapper.User.xml对应的test.dao.UserDao.java,具体如下所示,其实也没什么好说,就是一大堆方法的罗列,毕竟dao只是一个数据库接口而已。这里唯一需要大家注意的是,在SSM整合的过程中,我们需要对Dao层,标上@Repository的注解,让Spring能识别这是Dao层。

package test.dao;

import org.springframework.stereotype.Repository;

import test.entity.User;

@Repository
public interface UserDao {
	public User findUsersByUsername(String username);

	public int addUser(User user);

	public int modifyPasswordByUsername(User user);
}

同时也顺手完成刚才在test.mapper.User.xml提到的增删改查的使用和返回类型,实体类test.entity.User.java。这样的数据库~Java实体,典型的private+getter+setter结构,相信大家早就见惯不怪了。

package test.entity;

public class User {
	
	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;
	}

}

4、然后是Service层,也就是事务层,test.services.UserServices.java,这里主要为Action层提供一系列封装的方法,拿Action提供的数据操作数据库,并且处理完返回数据给Action来应对jsp和java的交互,这往往是网页工程的核心。

这里一样要严格注解一个@Service表示这是个事务层,不然Spring是直接识别不到报错的。

package test.services;

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

import test.dao.UserDao;
import test.entity.User;

@Service
public class UserServices {
	
	@Autowired
	private UserDao userDao;//自动注入的存在,无需getter和setter了

	/*各个业务*/
	
	//判断用户是否存在
	public boolean isUserExist(String username) {
		if (userDao.findUsersByUsername(username) == null) {
			return false;
		} else {
			return true;
		}
	}

	//根据提供的用户名拿密码
	public String getPasswordByUsername(String username) {
		return userDao.findUsersByUsername(username).getPassword();
	}

	//新增一个用户
	public void addUser(String username, String password) {
		User user = new User();
		user.setUsername(username);
		user.setPassword(password);
		userDao.addUser(user);
	}
  
	//修改某一用户的密码
	public void modifyPasswordByUsername(String username, String newpassword) {
		User user = userDao.findUsersByUsername(username);
		user.setUsername(username);
		user.setPassword(newpassword);
		userDao.modifyPasswordByUsername(user);
	}
	
}

另外,大家也可以从这个文件看到Mybatis比Hibernate优秀的原因,Mybatis处理数据库根本就没有什么commit不commit的提交事务才能修改数据库事情!他就是一个简单的SQL过程,上面的调用的dao方法,你完全可以理解成,这其实就是mapper一条对数据库操作的sql语句,执行即更改。

5、之后是test.actions.WebAction.java,这里也就是网页的Action层了,这个文件也在《【SpringMVC】Helloworld》(点击打开链接)中详细表述过了。

这里在SSM同样要明确地加上@Controller注解表示这是个Action层。

这里也同时展示了SpringMVC中Java是如何拿前台的数据,和返回数据到前台的。拿前台的数据主要是靠@RequestParam("前台表单的name")+后台Java的变量名了这个注解,当然还有拿其它数据的方式,不过这个是拿Post方法提交的表单数据最常用了,当然在get提供也可以照样拿,其余几种拿前台数据的方式比较少用,大家有兴趣可以某度一下。@RequestMapping注解指明servlet的url和get/post的使用方式。

而返回数据到前台,主要压在model里面,model可以放任何类型的东西,也就是objects。model可以用jsp3.0简单的表达式${}打印,要是里面放的是个list可以配合c标签来打印。

至于各个方法如何处理用户登录、注册、修改密码的细节,相信大家配合上面的test.services.UserServices.java一下就看得懂了,一点都不难,非常简单的逻辑判断。

package test.actions;

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 test.services.UserServices;

@Controller
public class WebAction {
	@Autowired
	private UserServices userServices;//自动注入的存在,getter和setter见鬼去吧!

	//跳转到本工程主页的action
	@RequestMapping(value = "/index")
	public String index() {
		return "index";
	}

	//关于用户登录的表单提交
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public String login(@RequestParam("username") String username,
			@RequestParam("password") String password, ModelMap model) {
		if (!userServices.isUserExist(username)) {
			model.addAttribute("msg", "用户名不存在!");
		} else {
			if (password.equals(userServices.getPasswordByUsername(username))) {
				model.addAttribute("msg", "登录成功!");
			} else {
				model.addAttribute("msg", "密码错误!");
			}
		}
		return "index";
	}

	//关于用户注册的表单提交
	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public String register(@RequestParam("username") String username,
			@RequestParam("password") String password, ModelMap model) {
		if (userServices.isUserExist(username)) {
			model.addAttribute("msg", "用户名已存在!");
		} else {
			userServices.addUser(username, password);
			model.addAttribute("msg", "注册成功!");
		}
		return "index";
	}

	//关于修改密码的表单提交
	@RequestMapping(value = "/modifyPassword", method = RequestMethod.POST)
	public String modifyPassword(@RequestParam("username") String username,
			@RequestParam("password") String password,
			@RequestParam("newpassword") String newpassword, ModelMap model) {
		if (!userServices.isUserExist(username)) {
			model.addAttribute("msg", "用户名不存在!");
		} else {
			if (password.equals(userServices.getPasswordByUsername(username))) {
				userServices.modifyPasswordByUsername(username, newpassword);
				model.addAttribute("msg", "修改密码成功!");
			} else {
				model.addAttribute("msg", "密码错误!");
			}
		}
		return "index";
	}
	
}

6、最后完成view\index.jsp这一页就大功告成了,views层也就是前端,非常简单的东西,不多赘述了。本文为了只是用jsp3.0的表达式简单打印了的string变量${msg},那些什么打印用户表就不做。要是model里面放的是个list,可以参考《【Servlet】利用Servlet3.0标准与JSTL表达式实现文件上传系统,支持图片上传后显示》( 点击打开链接)利用jstl表达式的c标签,<c:foreach>打印了,这里为了不杂糅jstl的技术,就不展示怎么打印用户表了。

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!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>主页</title>
</head>
<body>
	<p style="color:red">${msg}</p><hr>
	用户登录<br>
	<form action="login" method="post">
		用户名:<input type="text" name="username" /><br>
		密码:<input type="password" name="password" /><br>
		<input type="submit" value="提交"><br>
	</form><hr>
	用户注册<br>
	<form action="register" method="post">
		用户名:<input type="text" name="username" /><br>
		密码:<input type="password" name="password" /><br>
		<input type="submit" value="提交"><br>
	</form><hr>
	修改密码<br>
	<form action="modifyPassword" method="post">
		用户名:<input type="text" name="username" /><br>
		密码:<input type="password" name="password" /><br>
		新密码:<input type="password" name="newpassword" /><br>
		<input type="submit" value="提交"><br>
	</form><hr>		
</body>
</html>

最后,本文完成的例子可以在: http://download.csdn.net/download/yongh701/10124309,要是你的csdn下载分不多,或者我一样很反感csdn的最新的必须要下载分才能下载的下载机制,也可以到 https://github.com/yongh701/SSM下载。

大家看到这样一套下来,Spring+SpringMVC+Mybatis比Struts2+Hibernate3+Spring3更接地气,没有什么s标签,没有什么又要多开一个xml文件配action,也没有hibernate那套什么hql,完完全全就是你最常用的html语言和sql查询。所以SSM逐渐流行起来了,其实在2014年甚至更早的时候,大家都已经对Struts2、Hibernate3颇有微词,而随着Spring的普及,中文资料渐渐增多,它已经不再单纯是一个java~xml交互工具。简单的注解方法,避免以前大量的xml文件编写,SpringMVC的高安全性,更加让SSM成为业内的新宠!

猜你喜欢

转载自blog.csdn.net/yongh701/article/details/78571831
今日推荐