Spring整合SpringMVC與Mybatis(SSM)實(shí)現(xiàn)完整登錄功能流程詳解
項(xiàng)目演示
演示中只用一個(gè)用戶登錄,只是為了測試功能,實(shí)際使用中是根據(jù)數(shù)據(jù)庫表內(nèi)數(shù)據(jù)來決定的。

1 創(chuàng)建工程完成配置
1 ieda新建maven項(xiàng)目名字隨便起
2 點(diǎn)擊文件,項(xiàng)目 ,模塊 ,點(diǎn)加號添加web模塊 ,這里要注意文件路徑

我們改一下第一項(xiàng)的路徑 從web 改成src\main\webapp

下面Web資源目錄也改一下

選擇webapp 點(diǎn)擊右下角創(chuàng)建工件系統(tǒng)自動創(chuàng)建工件,點(diǎn)確認(rèn)

發(fā)現(xiàn)我們webapp有個(gè)小藍(lán)點(diǎn)就算成功了。
這個(gè)時(shí)候先在java包下建一個(gè)test類構(gòu)建一下項(xiàng)目,看一下target包出來沒,如果先配置tomcat target得后期手動拉出來,很麻煩。

現(xiàn)在開始配tomcat 點(diǎn)擊右上角添加配置

點(diǎn)擊加號選擇tomcat本地
點(diǎn)擊配置,主目錄放我們tomcat的文件夾,系統(tǒng)會自動生成其他的

完成后點(diǎn)右下角的小紅燈泡配置工件,進(jìn)去后不用動,把下面的應(yīng)用程序上下文改為 “/” 就行。

點(diǎn)擊確認(rèn)。 為了驗(yàn)證配置是否可用進(jìn)入webapp目錄下,新建一個(gè)index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<h1> 配置完成,終于可以開始了</h1>
</body>
</html>點(diǎn)擊gebug啟動tomcat ,根據(jù)之前的端口在瀏覽器看看有沒有我們寫的網(wǎng)頁

如果網(wǎng)頁顯示正常我們開始添加依賴和寫配置文件。
pom.xml 這里只顯示需要加的,每個(gè)依賴我也標(biāo)上了注釋
<repositories>
<repository>
<id>aliyun</id>
<name>aliyun</name>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
</repositories>
<dependencies>
<!-- webmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.8</version>
</dependency>
<!-- json序列化-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
<!-- JDBC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.8</version>
</dependency>
<!-- mybatis-plus 自動引入mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- druid 連接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<!-- junit單元測試-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.8</version>
</dependency>
<!-- javax.servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
<!--只在測試時(shí)用-->
</dependency>
<!-- 日志組件-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- MD5加密組件-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.12.1</version>
</dependency>
</dependencies>在resources下新建applicationContext.xml 來作為配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
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/task
http://www.springframework.org/schema/task/spring-task.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">
<!-- 組件掃描,完成對象的創(chuàng)建與初始化 base-package寫自己的 -->
<context:component-scan base-package="com.xatu"/>
<!-- 開啟注解模式-->
<mvc:annotation-driven>
<!-- 消息轉(zhuǎn)換器-->
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<!--設(shè)置屬性 媒體類型(list集合)-->
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=utf-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- 把靜態(tài)資源排除在外-->
<mvc:default-servlet-handler/>
<!--MyBatis與Spring的整合配置 -->
<!--1.配置數(shù)據(jù)源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!-- 實(shí)例化DruidDataSource設(shè)置與連接相關(guān)的屬性-->
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<!-- jdbc驅(qū)動-->
<property name="url" value="jdbc:mysql://localhost:3306/cnpc_comment?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"/>
<!-- URL連接字符串 用戶名密碼寫自己mysql數(shù)據(jù)庫的賬號密碼-->
<property name="username" value="******"/>
<!-- 用戶名-->
<property name="password" value="******"/>
<!-- 密碼-->
<property name="initialSize" value="5"/>
<!-- 初始化時(shí)幾個(gè)數(shù)據(jù)庫連接,初始數(shù)量-->
<property name="maxActive" value="20"/>
<!-- 最大數(shù)量-->
</bean>
<!--2.配置SessionFactoryBean-->
<!--SqlSessionFactoryBean用于根據(jù)配置信息創(chuàng)建SqlSessionFactory,不再需要我們自己編碼創(chuàng)建-->
<!-- 沒有引入mybatis-plus之前的 <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">-->
<bean id="sessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 數(shù)據(jù)源 ref關(guān)聯(lián)到 上面的dataSource對象-->
<property name="mapperLocations" value="classpath:mappers/*.xml"/>
<!-- 加載對象過程中掃描哪個(gè)文件 保存sql文件的xml-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 本身框架配置文件路徑-->
<!-- MyBaits Plus 3.4以后版本需要在MybatisSqlSessionFactoryBean.plugins屬性中進(jìn)行設(shè)置 -->
<property name="plugins">
<array>
<bean class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor">
<property name="interceptors">
<list>
<bean class="com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor"/>
</list>
</property>
</bean>
</array>
</property>
<!-- 插件配置項(xiàng) 代表一系列插件,
實(shí)例化一個(gè)MybatisPlusInterceptor插件容器
用interceptors進(jìn)行指定
-->
</bean>
<!--3.配置Mapper掃描器 value 寫自己mapper的位置-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xatu.mapper"/>
</bean>
<!-- 聲明式事務(wù)配置-->
<!-- 1,定義事務(wù)管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 2,開啟注解模式的聲明式事務(wù)-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>mybatis.config
<?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>
<!-- 駝峰命名轉(zhuǎn)換-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- MyBatis Plus 3.4版本以前配置分頁插件 -->
<!--<plugins>
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"></plugin>
</plugins>-->
</configuration>logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!--向控制臺書寫日志的追加器-->
<encoder>
<pattern>%d{HH:mm:ss} %-5level [%thread] %logger{30} - %msg%n</pattern>
<!-- 線程名字,產(chǎn)生日志的時(shí)間,日志的級別,由哪個(gè)類產(chǎn)生的日志-->
<charset>GBK</charset>
</encoder>
</appender>
<root level="debug">
<!-- 最低允許輸出debug級別的日志,日志向控制臺進(jìn)行輸出-->
<appender-ref ref="console"/>
</root>
</configuration>mappers包下的manager.xml 他要跟自己的mapper包進(jìn)行綁定 由于用的mybatis-plus所以不用自己寫語句
<?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="com.xatu.mapper."> </map
基本配置就完成了
2 表設(shè)計(jì)
表名叫manager (實(shí)體類要綁定的注意)

3 實(shí)體類
@TableName("manager")
public class Manager {
@TableId(type = IdType.AUTO)
private Long managerId;
private String username;
private String password;
private Integer salt;
@Override
public String toString() {
return "Manager{" +
"userId=" + managerId +
", username='" + username + '\'' +
", password='" + password + '\'' +
", salt=" + salt +
'}';
}
public Long getUserId() {
return managerId;
}
public void setUserId(Long userId) {
this.managerId = userId;
}
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 Integer getSalt() {
return salt;
}
public void setSalt(Integer salt) {
this.salt = salt;
}
}4 mapper
public interface ManagerMapper extends BaseMapper<Manager> {
}5 service
public interface ManagerService {
public Manager checkLogin1(String username, String password);
}Impl 實(shí)現(xiàn)類
先使用mapper查看是否用這個(gè)用戶名的用戶再調(diào)用用戶表的信息來判斷密碼是否正確,我們這里假設(shè)沒有重名用戶。
@Service
//默認(rèn)方法不開啟事務(wù)
@Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
public class ManagerServiceImpl implements ManagerService {
@Resource
private ManagerMapper managerMapper;
@Transactional(rollbackFor = Exception.class)
@Override
public Manager checkLogin1(String username, String password) {
QueryWrapper<Manager> wrapper = new QueryWrapper();
wrapper.eq("username", username);
Manager manager = managerMapper.selectOne(wrapper);
if (manager == null) {
throw new MemberException("用戶不存在");
}
String md5 = MD5Utils.md5Digest(password, manager.getSalt());
if (!md5.equals(manager.getPassword())) {
throw new MemberException("您輸入的密碼有誤");
}
return manager;
}
}異常
public class MemberException extends RuntimeException{
public MemberException(String message){
super(message);
}
}6 controller
調(diào)用service的chedkLogin1方法來檢驗(yàn)登錄 為了安全,在成功登錄后我們將密碼 和鹽值 設(shè)為null
@RestController
@RequestMapping("/api/manager")
public class ManagerController {
@Resource
private ManagerService managerService;
@PostMapping("/check_login1")
public ResponseUtils checkLogin1(String username , String password){
ResponseUtils resp ;
resp = new ResponseUtils();
try {
Manager manager = managerService.checkLogin1(username, password);
manager.setPassword(null);
manager.setSalt(null);
resp = new ResponseUtils().put("manager" , manager);
}catch (Exception e){
e.printStackTrace();
resp = new ResponseUtils(e.getClass().getSimpleName(), e.getMessage());
}
return resp;
}
}7 工具類
MD5
用來使用hash算法使密碼變復(fù)雜
public class MD5Utils {
public static String md5Digest(String source ,Integer salt){
char[] ca = source.toCharArray();
for(int i = 0 ; i < ca.length ;i++){
ca[i] = (char) (ca[i] + salt);
}
String target = new String(ca);
String md5 = DigestUtils.md5Hex(target);
return md5;
}
}統(tǒng)一返回對象
public class ResponseUtils {
private String code;//服務(wù)處處理編碼
private String message;//服務(wù)器返回消息
private Map data = new LinkedHashMap<>();//服務(wù)器返回的數(shù)據(jù)
//成功
public ResponseUtils(){
this.code = "0";
this.message = "success";
}
//失敗,傳入編碼和消息
public ResponseUtils(String code , String message){
this.code = code;
this.message = message;
}
//給data進(jìn)行賦值
public ResponseUtils put(String key , Object value){
this.data.put(key, value);
return this;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Map getData() {
return data;
}
public void setData(Map data) {
this.data = data;
}
}整體

8 前端頁面
我們是有vue 并且使用element-plus組件庫來簡化和美化我們的頁面

這里我選擇的是創(chuàng)建靜態(tài)文件包,里面放著常用文工具,需要的時(shí)候直接把包放在webapp下載頁面編寫時(shí)進(jìn)行調(diào)用。沒有的話請選擇替他方法,方法很多。
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄</title>
<!-- 引入樣式 -->
<link rel="stylesheet" type="text/css" href="assets/element-plus/index.css" rel="external nofollow" >
<!-- 引入組件庫 -->
<script src="/assets/vue/vue.global.js"></script>
<script src="/assets/element-plus/index.full.js"></script>
<script src="/assets/axios/axios.js"></script>
<style>
.login-box {
border: 1px solid #DCDFE6;
width: 350px;
margin: 180px auto;
padding: 35px 35px 15px 35px;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
box-shadow: 0 0 25px #909399;
}
.login-title{
text-align: center;
margin: 0 auto 40px auto;
color: #303133;
}
</style>
</head>
<body>
<div id="app">
<el-form ref="loginForm" label-width="80px" :rules="rules" :model="form" class="login-box">
<h2 class="login-title">登錄</h2>
<el-form-item label="賬號" prop="username">
<el-input type="text" placeholder="請輸入賬號" v-model="form.username"></el-input>
</el-form-item>
<el-form-item label="密碼" prop="password">
<el-input type="password" placeholder="請輸入密碼" v-model="form.password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" v-on:click="onSubmit('loginForm')" style="width:200px">登錄</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" v-on:click="returnBack" style="width:200px">退出</el-button>
</el-form-item>
</el-form>
</div>
<script>
const Main = {
data() {
return {
form: {
username: ''
,password: ''
}
,rules:{
username: [
{required: true,message : '賬號不能為空' , trigger:'blur'}
],
password:[
{required: true,message : '密碼不能為空' , trigger:'blur'}
]
}
}
}
,methods : {
onSubmit(formName){
const objApp = this;
const form = this.$refs[formName];
form.validate((valid) => {
if(valid){
console.info("表單校驗(yàn)成功,準(zhǔn)備提交數(shù)據(jù)");
const form = this.form;
const $message = this.$message;
const params = new URLSearchParams();
params.append("username", form.username);
params.append("password", form.password);
axios.post("/api/manager/check_login1", params)
.then(function (response) {
console.info(response);
const json = response.data;
if(json.code=="0"){
window.location.href = "/index1.html";
}else{
$message.error({message:json.message, offset: 100});
}
});
}
})
}
,returnBack : function (){
window.location.href = "/index.html";
}
}
};
//初始化Vue,綁定Main中的數(shù)據(jù),利用ElementPlus對#app容器進(jìn)行重新渲染
const app = Vue.createApp(Main);
app.use(ElementPlus);
app.mount("#app");
</script>
</body>
</html>至于另外兩個(gè)頁面,只是使用a標(biāo)簽添加鏈接 因?yàn)橹皇堑卿浌δ軟]有下一步所以建立兩個(gè)網(wǎng)頁來判斷跳轉(zhuǎn)與登錄是否成功
總結(jié)
這算是完成了基礎(chǔ)的登錄功能,雖然我們并沒有涉及到使用到session去保存用戶信息以及去進(jìn)行權(quán)限的判定,但是這個(gè)項(xiàng)目算是已經(jīng)為后續(xù)的工作完成了基礎(chǔ)的搭建后面只要在庫中新建表或者在manager表上進(jìn)行擴(kuò)充,改寫實(shí)體類并進(jìn)行設(shè)計(jì)就可以添加更多的功能,這個(gè)前端登錄頁面也可以作為一個(gè)通用化的頁面,只需要改變里面的的api接口就能做到重復(fù)使用。
到此這篇關(guān)于Spring整合SpringMVC與Mybatis(SSM)實(shí)現(xiàn)完整登錄功能流程詳解的文章就介紹到這了,更多相關(guān)Spring登錄功能內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實(shí)現(xiàn)獲取指定個(gè)數(shù)的不同隨機(jī)數(shù)
今天小編就為大家分享一篇關(guān)于Java實(shí)現(xiàn)獲取指定個(gè)數(shù)的不同隨機(jī)數(shù),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-01-01
詳解如何在Spring中為@Value注解設(shè)置默認(rèn)值
在Spring開發(fā)中,我們經(jīng)常會遇到需要從配置文件中讀取屬性的情況,@Value注解是Spring提供的一種便捷方式,能夠讓我們輕松地將配置文件中的屬性注入到Spring Bean中,2024-10-10
Java中實(shí)現(xiàn)二叉樹的遍歷與重構(gòu)
這篇文章主要介紹了Java中實(shí)現(xiàn)二叉樹的遍歷與重構(gòu),樹是一種非線性的數(shù)據(jù)結(jié)構(gòu),它是由n(n>=0)個(gè)有限結(jié)點(diǎn)組成一個(gè)具有層次關(guān)系的集合,把它叫做樹是因?yàn)樗雌饋硐褚豢玫箳斓臉?也就是說它是根朝上,而葉朝下的,需要的朋友可以參考下2023-10-10
詳解SpringBoot配置devtools實(shí)現(xiàn)熱部署
本篇文章主要介紹了詳解SpringBoot配置devtools實(shí)現(xiàn)熱部署 ,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
如何使用Java 8 中的 Stream 遍歷樹形結(jié)構(gòu)
這篇文章主要介紹了使用Java 8中的Stream遍歷樹形結(jié)構(gòu),我們可以使用Java8中的Stream流一次性把數(shù)據(jù)查出來,然后通過流式處理,我們一起來看看,代碼實(shí)現(xiàn)為了實(shí)現(xiàn)簡單,就模擬查看數(shù)據(jù)庫所有數(shù)據(jù)到List里面,需要的朋友可以參考下2023-08-08
springboot整合redis過期key監(jiān)聽實(shí)現(xiàn)訂單過期的項(xiàng)目實(shí)踐
現(xiàn)在各種電商平臺都有自己的訂單過期時(shí)間設(shè)置,那么如何設(shè)置訂單時(shí)間過期呢,本文主要介紹了springboot整合redis過期key監(jiān)聽實(shí)現(xiàn)訂單過期的項(xiàng)目實(shí)踐,感興趣的可以了解一下2023-12-12

