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

Spring 4 + Spring MVC + MyBatis 登錄註冊完整實戰:分層架構、註解驅動、事務管理、RESTful 風格

     編輯:Java 綜合教學

Spring 4 + Spring MVC + MyBatis 登錄註冊完整實戰

本項目演示經典三層架構 (Controller-Service-Mapper) 整合,採用全註解驅動、Java Config 風格 XML、MyBatis 註解映射、聲明式事務、RESTful URL 設計,適合作為中小型項目脚手架參考。

一、項目結構

src/
├── main/
│   ├── java/com/mstf/
│   │   ├── controller/     # FormController, UserController
│   │   ├── domain/         # User 實體
│   │   ├── mapper/         # UserMapper (MyBatis 註解)
│   │   ├── service/        # UserService 接口 + UserServiceImpl
│   │   └── config/         # (可選) Java Config 類
│   ├── resources/
│   │   ├── db.properties       # 數據源參數
│   │   ├── log4j.properties    # 日誌配置
│   │   └── mybatis-config.xml  # MyBatis 全局配置 (可選)
│   └── webapp/
│       ├── WEB-INF/
│       │   ├── jsp/            # loginForm, regeister, index, success
│       │   ├── applicationContext.xml  # 根容器:Service/Mapper/事務/數據源
│       │   ├── springmvc-config.xml  # Web 容器:Controller/視圖解析/靜態資源
│       │   └── web.xml         # 部署描述符
│       └── static/             # 靜態資源 (CSS/JS/圖片)
└── test/

二、核心代碼層層解析

1. 實體層

public class User implements Serializable {
    private int id;
    private String username, password, phone, email;
    // 全參/無參構造器、getter/setter、toString
}

2. Mapper 層 (MyBatis 註解映射,無 XML)

public interface UserMapper {
    @Select("SELECT * FROM loginuser WHERE username=#{username} AND password=#{password}")
    User findWithLoginnameAndPassword(@Param("username") String username, @Param("password") String password);

    @Insert("INSERT INTO loginuser(username,password,phone,email) VALUES(#{username},#{password},#{phone},#{email})")
    int regeist(@Param("username") String username, @Param("password") String password, 
                @Param("phone") String phone, @Param("email") String email);
}

3. Service 層 (接口 + 實現 + 事務註解)

public interface UserService {
    User login(String username, String password);
    int regeist(User user);
}

@Service("userService")
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public class UserServiceImpl implements UserService {
    @Autowired private UserMapper userMapper;

    @Transactional(readOnly = true)
    @Override public User login(String username, String password) {
        return userMapper.findWithLoginnameAndPassword(username, password);
    }

    @Override public int regeist(User user) {
        return userMapper.regeist(user.getUsername(), user.getPassword(), 
                                    user.getPhone(), user.getEmail());
    }
}

4. Controller 層 (RESTful + 視圖跳轉)

@Controller
public class FormController {
    @RequestMapping(value = "/{formName}")
    public String loginForm(@PathVariable String formName) {
        return formName; // 動態跳轉 loginForm, regeister 等
    }
}

@Controller
public class UserController {
    @Autowired @Qualifier("userService") private UserService userService;

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public ModelAndView login(String username, String password, ModelAndView mv, HttpSession session) {
        User user = userService.login(username, password);
        if (user != null) {
            session.setAttribute("user", user);
            mv.setView(new RedirectView("/Demo4/index")); // 重定向防重複提交
        } else {
            mv.addObject("message", "登錄名或密碼錯誤");
            mv.setViewName("loginForm");
        }
        return mv;
    }

    @RequestMapping(value = "/regeist", method = RequestMethod.POST)
    public String regeist(@ModelAttribute("user") User user) {
        userService.regeist(user);
        return "success";
    }
}

三、Spring 容器配置 (雙容器架構)

applicationContext.xml (根容器:業務層)

<beans ... xmlns:mybatis="https://mybatis.org/schema/mybatis-spring" 
         xmlns:tx="https://www.springframework.org/schema/tx">

    <mybatis:scan base-package="com.mstf.mapper" /> <!-- 掃描 Mapper 接口生成代理 -->
    <context:component-scan base-package="com.mstf" /> <!-- 掃描 @Service/@Component -->
    <context:property-override location="classpath:db.properties" /> <!-- 覆蓋屬性佔位符 -->

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" /> <!-- 屬性來自 db.properties -->

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" p:dataSource-ref="dataSource" />

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource" />
    <tx:annotation-driven transaction-manager="txManager" /> <!-- 啟用 @Transactional -->
</beans>

springmvc-config.xml (Web 容器:表現層)

<beans ... xmlns:mvc="https://www.springframework.org/schema/mvc">
    <context:component-scan base-package="com.mstf.controller" /> <!-- 僅掃描 Controller -->
    <mvc:annotation-driven /> <!-- 啟用 @RequestMapping/@RequestBody 等 -->
    <mvc:default-servlet-handler /> <!-- 靜態資源交給容器默認 Servlet -->

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

四、web.xml 雙容器啟動

<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>

<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/springmvc-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<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>

五、JSP 視圖 (EL + JSTL)

<!-- loginForm.jsp -->
<form action="${pageContext.request.contextPath}/login" method="post">
    <font color="red">${requestScope.message}</font>
    登錄名: <input name="username" required maxlength="16">
    密碼: <input type="password" name="password" required maxlength="16">
    <input type="submit" value="登錄">
    <a href="${pageContext.request.contextPath}/regeister">立即注冊</a>
</form>

<!-- index.jsp (登錄成功) -->
歡迎, ${sessionScope.user.username}!

六、關鍵設計亮點總結

  1. 分層解耦:Controller 不含業務,Service 不含 SQL,Mapper 只做映射
  2. 註解驅動:@Service/@Autowired/@Transactional/@RequestMapping/@Select/@Insert
  3. 雙容器隔離:根容器管 Service/Mapper/事務,Web 容器管 Controller/視圖,防止 Bean 重複掃描
  4. RESTful 風格:POST /login、POST /regeist、動態跳轉 /{formName}
  5. 重定向防重複提交:登錄成功 RedirectView 到 /index
  6. 編碼統一:Filter + db.properties UTF-8 全鏈路
  7. MyBatis 註解映射:簡單 SQL 無需 XML,減少文件切換

此架構雖為 Spring 4 時代經典,但分層原則、註解驅動、雙容器隔離、事務邊界、RESTful 設計 至今仍是 Spring Boot 微服務架構的基因基石。理解透徹,遷移無障礙。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved