首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring MVC + MyBatis + MySQL 整合項目搭建完整教程(含分層架構、分頁、登錄實戰)

     編輯:Java 綜合教學

Spring MVC + MyBatis + MySQL 整合項目搭建完整教程

開發環境

  • OS: Windows 64 / Linux
  • JDK: 1.7+ (建議 8/11/17 LTS)
  • IDE: Eclipse / IntelliJ IDEA
  • Server: Tomcat 7/8/9
  • DB: MySQL 5.6+

項目結構

src/
├── main/
│   ├── java/
│   │   └── com.springmvc/
│   │       ├── action/      # 控制層
│   │       ├── dao/         # 數據訪問接口
│   │       ├── model/       # 實體類
│   │       ├── service/     # 業務接口
│   │       └── service/impl/# 業務實現
│   ├── resources/
│   │   ├── spring-mybatis/  # Spring+MyBatis 配置
│   │   │   └── spring-mybatis-config.xml
│   │   └── com/springmvc/sqlmap/ # MyBatis XML 映射
│   │       └── UserEntity.xml
│   └── webapp/
│       ├── WEB-INF/
│       │   ├── view/        # JSP 視圖
│       │   │   ├── login.jsp
│       │   │   └── index.jsp
│       │   ├── web.xml
│       │   └── dispatcher-servlet.xml
│       └── static/          # 靜態資源
│           ├── bootstrap/
│           ├── jquery/
│           └── js/
└── test/

項目結構截圖

核心配置文件

1. spring-mybatis-config.xml (數據源、事務、SqlSession、掃描)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="https://www.springframework.org/schema/aop"
       xmlns:tx="https://www.springframework.org/schema/tx"
       xmlns:context="https://www.springframework.org/schema/context"
       xsi:schemaLocation="...省略...">

    <!-- 組件掃描 -->
    <context:component-scan base-package="com.springmvc.dao"/>
    <context:component-scan base-package="com.springmvc.service"/>

    <!-- 屬性佔位符 -->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>

    <!-- 數據源 (DBCP) -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
        <property name="maxActive" value="100"/>
        <property name="maxIdle" value="30"/>
        <property name="maxWait" value="500"/>
    </bean>

    <!-- SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath*:com/springmvc/sqlmap/*.xml"/>
    </bean>

    <!-- SqlSessionTemplate -->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

    <!-- 事務管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- AOP 事務切面 (Service 層) -->
    <aop:config>
        <aop:advisor pointcut="execution(* com.springmvc..service..*.*(..))" advice-ref="txAdvice"/>
    </aop:config>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="select*" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!-- Mapper 接口自動代理 -->
    <bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="mapperInterface" value="com.springmvc.dao.UserDao"/>
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
</beans>

2. 實體類 User.java

package com.springmvc.model;
import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID = -8772180261203847538L;
    private Long id;
    private String name;
    private String email;
    private String isEmail;   // '1' 已驗證
    private String password;
    private String isDelete;  // '0' 正常
    // Getter/Setter 省略...
}

3. Dao 接口 UserDao.java

package com.springmvc.dao;
import java.util.List;
import com.springmvc.model.User;

public interface UserDao {
    List<User> getUser(User user);
}

4. Service 接口與實現

// UserService.java
package com.springmvc.service;
import java.util.List;
import com.springmvc.model.User;
public interface UserService {
    List<User> getUser(User user);
}

// UserServiceImpl.java
package com.springmvc.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.springmvc.dao.UserDao;
import com.springmvc.model.User;
import com.springmvc.service.UserService;

@Service
public class UserServiceImpl implements UserService {
    @Autowired private UserDao userDao;
    @Override public List<User> getUser(User user) { return userDao.getUser(user); }
}

5. MyBatis 映射 UserEntity.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.springmvc.dao.UserDao">
    <resultMap id="rm_user" type="com.springmvc.model.User">
        <result property="id" column="id" jdbcType="NUMERIC"/>
        <result property="name" column="name" jdbcType="VARCHAR"/>
        <result property="email" column="email" jdbcType="VARCHAR"/>
        <result property="isEmail" column="isEmail" jdbcType="VARCHAR"/>
        <result property="password" column="password" jdbcType="VARCHAR"/>
        <result property="isDelete" column="isDelete" jdbcType="VARCHAR"/>
    </resultMap>

    <select id="getUser" resultMap="rm_user" parameterType="com.springmvc.model.User">
        select * from user
        <where>
            1=1
            <if test="name != null and name != ''">
                and name = #{name}
            </if>
            <if test="password != null and password != ''">
                and password = #{password}
            </if>
            and isEmail = '1'
            and isDelete = '0'
        </where>
    </select>
</mapper>

6. web.xml (核心 Servlet 配置)

<web-app version="3.0" ...>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring-mybatis/spring-mybatis-config.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 編碼過濾器 -->
    <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>
        <init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param>
    </filter>
    <filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

    <!-- DispatcherServlet -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>

    <welcome-file-list><welcome-file>index.html</welcome-file></welcome-file-list>
</web-app>

7. dispatcher-servlet.xml (MVC 配置)

<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:mvc="https://www.springframework.org/schema/mvc"
       xmlns:context="https://www.springframework.org/schema/context"
       xsi:schemaLocation="...省略...">
    <context:annotation-config/>
    <context:component-scan base-package="com.springmvc.action"/>
    
    <!-- JSON 轉換 -->
    <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
    <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
        <property name="mediaTypes">
            <value>json=application/json html=text/html</value>
        </property>
    </bean>

    <!-- 視圖解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

前端頁面與交互

登錄頁 login.jsp (Bootstrap + Tab 切換)

<%@ page pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<% String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/"; %>
<html>
<head>
    <jsp:include page="/WEB-INF/util/bootstrap.jsp"/>
    <script src="<%=basePath%>static/view/js/login.js"></script>
</head>
<body>
<div class="tab-content" style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:300px;">
    <ul class="nav nav-tabs">
        <li class="active"><a href="#login" data-toggle="tab">登錄</a></li>
        <li><a href="#register" data-toggle="tab">注冊</a></li>
    </ul>
    <form class="tab-pane fade in active" id="login" onsubmit="return false;">
        <c:if test="${not empty error}"><div class="alert alert-danger"><c:out value="${error}"/></div></c:if>
        <input id="login-email" name="email" class="form-control login-input" placeholder="郵箱">
        <input type="password" name="password" id="login-password" class="form-control login-input" placeholder="密碼">
        <div class="checkbox"><label><input type="checkbox" id="login-remember"> 記住我</label></div>
        <button class="btn btn-lg btn-primary btn-block" onclick="loginFunction.loginSubmit();">登錄</button>
    </form>
    <form class="tab-pane fade" id="register" onsubmit="return false;">...</form>
</div>
</body></html>

JS 模塊 login.js

var loginFunction = {
    loginSubmit: function() {
        var email = $("#login-email").val();
        var password = $("#login-password").val();
        if (!email) { alert("請輸入郵箱"); return; }
        if (!password) { alert("請輸入密碼"); return; }
        
        $.ajax({
            url: basePath + "101/loginCheck.htm",
            type: "post",
            data: {email: email, password: password}, // 實際應加密傳輸
            dataType: "json",
            success: function(data) {
                if (data.status == "success") 
                    window.location.href = basePath + "101/index.htm";
                else 
                    alert("用戶名或密碼錯誤");
            }
        });
    }
};
$(function() {});

Controller IndexAction.java

package com.springmvc.action;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import com.springmvc.model.User;
import com.springmvc.service.UserService;

@Controller
@RequestMapping("/101")
public class IndexAction {
    @Autowired private UserService userService;

    @RequestMapping("/index.htm")
    public String index() { return "index"; }

    @RequestMapping("/login.htm")
    public String login() { return "login"; }

    @RequestMapping(value="/loginCheck.htm", method=RequestMethod.POST)
    @ResponseBody
    public Map<String,Object> loginCheck(User user) {
        List<User> list = userService.getUser(user);
        Map<String,Object> map = new HashMap<>();
        if (list != null && !list.isEmpty()) {
            map.put("status", "success");
            map.put("message", "驗證成功");
            // 實際應:生成 Token、存 Session/Redis、密碼 BCrypt 驗證
        }
        return map;
    }
}

訪問入口

https://localhost:8080/項目名/101/login.htm

擴展建議

  1. 密碼加密:BCrypt / SCrypt
  2. 分頁查詢:PageHelper / MyBatis 分頁插件
  3. 參數校驗:JSR-303 @Valid + BindingResult
  4. 異常統一處理:@ControllerAdvice + @ExceptionHandler
  5. 靜態資源映射:<mvc:resources mapping="/static/**" location="/static/"/>
  6. 熱部署:Spring Loaded / JRebel / IDEA 熱部署
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved