【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成爲業內的新寵!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章