1. 程式人生 > 實用技巧 >Spring 入門(二) 使用SpringMVC

Spring 入門(二) 使用SpringMVC

1.Spring MVC依賴於Spring核心,實現了傳統MVC三層架構

完整流程如下

可總結出 Spring MVC 的工作流程如下:
1.客戶端請求提交到 DispatcherServlet。
2.由 DispatcherServlet 控制器尋找一個或多個 HandlerMapping,找到處理請求的 Controller。
3.DispatcherServlet 將請求提交到 Controller。
4.Controller 呼叫業務邏輯處理後返回 ModelAndView。
5.DispatcherServlet 尋找一個或多個 ViewResolver 檢視解析器,找到 ModelAndView 指定的檢視。
6.檢視負責將結果顯示到客戶端。

DispatcherServlet、HandlerMapping、Controller 和 ViewResolver 是springMVC中比較重要4個介面,感興趣可以查資料詳細瞭解

2.建立SpringMVC專案

1.開啟IDEA->new project->Maven 記得勾選create from archetype


直接點選到最後一步

2.建立完專案還缺少一些檔案目錄,需要建立缺少的資料夾

目錄說明:
main/java 生產環境程式碼主目錄
-com.mike 包名,根據情況建立
--common 公用類目錄
--controller 控制器目錄,處理客戶端請求,呼叫service處理業務
--dao 資料訪問物件查程式碼目錄,主要是增刪改
--entity 資料表實體類目錄,與資料庫表對應的類,屬性與欄位對應
--pojo 普通實體類目錄,不需要與表屬性對應
--service 服務類目錄,主要是呼叫一個或多個dao

webapp 靜態資源主目錄
jsp jsp檢視檔案目錄
web.xml檔案 serlvet原生配置,在springmvc中主要是配置DispatcherServlet 來接管所有請求
springmvc-serlvet.xml檔案 bean配置,配置檢視解析器,及靜態資源可見性,及使用@AutoWried自動註解時需要掃描的包目錄

test/java 測試環境程式碼主目錄
-com.mike 包名,根據情況建立

3.編寫配置檔案

1.在WEB-INF目錄下找到web.xml 沒有就新建

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>springMVC-demo1</display-name>
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

2.在WEB-INF下新建springmvc-servlet.xml檔案

<?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: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.xsd
           http://www.springframework.org/schema/context
           https://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--基於註解的注入需要配置掃描包-->
    <context:component-scan base-package="com.mike"/>
    <!-- annotation-driven用於簡化開發的配置,註解DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter -->
    <mvc:annotation-driven/>
    <!--允許css目錄下檔案可見-->
    <mvc:resources location="/css/" mapping="/css/**" />
    <!-- 允許html目錄下的所有檔案可見 -->
    <mvc:resources location="/html/" mapping="/html/**"/>
    <!-- 允許image目錄下的所有檔案可見 -->
    <mvc:resources location="/images/" mapping="/images/**"/>
    <!--檢視配置器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

3.SpringMVC常用的註解

註解在java中的作用簡單可以理解為程式碼中帶@特殊標記,這些標記有不同種類,功能也不同,註解是java的語法特性,使用者可以自定義註解,jdk也自帶一些註解,這兩種註解都會被jvm處理

  • javax.annotation.Resource包下的@Resource(name="bean_name") 自帶註解,當一個構造方法,或setter,或屬性被申明為@Resource註解時,容器會例項化其引用的物件例項,而無須手動例項化
  • org.springframework.stereotype.Controller包下的@Controller,申明該類為控制器,當客戶端請求到來,會被用來處理請求
  • org.springframework.stereotype.Service包下的@Service ,申明該類為服務,可以在Controller呼叫該服務
  • org.springframework.stereotype.Repository包下的@Repository,申明該類為dao及資料訪問物件,可以該類中實現對資料庫增刪改查
  • org.springframework.stereotype.Component 包下的@Component ,申明該類為普通的pojo類,及普通實體類
  • org.springframework.beans.factory.annotation.Autowired包下的@AutoWired; 申明後,使用容器自動註解,容器會根據xml中配置的包路徑,掃描該引用的例項,並繫結到該類中
  • org.springframework.web.bind.annotation.RequestMapping下的@RequestMapping;申明後,將該方法與路由繫結,使用者可以通過路由訪問該方法

注意: 上述註解中 @Resource 和@AutoWired註解主要用來進行依賴注入,而當使用@AutoWried時,引用的類有多個例項時,建議使用@Qualifier註解,該註解基於name來查詢例項,可以衝突

在springMVC中注入其他類基本上是利用spring核心的容器實現即

  • setter注入,
  • 構造方法注入
  • 屬性注入
    下面簡述一下使用三種方法注入

1.setter注入,推薦使用,當引用的物件可能會經常變化時使用


public class UserController {
    public UserService userService;
     
    @AutoWried
    public void setUserService(UserService userService) { // 在類中申明要引用類的setter方法,容器會自動注入該引用的類例項
        this.userService = userService
    }

    //使用userService 物件
}

2.構造方注入,也推薦使用,當引用的物件不經常變化時使用

public class UserController{
    public UserService userService;
    
    @AutoWried
    UserController(UserService userService) { //在類的構造方法引數中申明要引用類的變數,容器會自動注入該引用的例項
        this.userService = userService;
    }

    //使用userService物件
}

3.屬性注入,該注入方式最簡單,只需在引用的類屬性上加入@AutoWried即可,但是不推薦使用該方法,spring官方也說明不推薦使用屬性注入,具體原因可以查閱資料

public class UserController{
    @AutoWired
    public UserService userService;

    //使用userService物件
}

4.完整例子

在controller目錄下新建UserController類檔案

package com.mike.controller;

import javax.servlet.http.HttpSession;
import com.mike.pojo.UserForm;
import com.mike.service.UserService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;

@Controller
@RequestMapping(value="/user")
public class UserController {
    public UserService userService;

    @Autowired
    UserController(UserService userService) { //構造方法注入UserService實現類,當有多個UserService實現類使用@Qualifier註解
        this.userService = userService;
    }

//    @Autowired
//    public void setUserService(UserService userService) { // setter注入UserService實現類
//        this.userService = userService;
//    }

    @RequestMapping(value = "/login")
    public String login(UserForm user,HttpSession session,Model model) { //當表單name和UserForm的屬性一致時會自動將表單值填入UserForm中
        if(userService.login(user)) { //判斷使用者名稱和密碼是否正確
            session.setAttribute("user",user);
            System.out.println("登陸成功");
            return "main";
        } else {
            model.addAttribute("messageError","使用者名稱或密碼錯誤"); //當登陸失敗提示資訊,並跳轉到登陸頁面
            System.out.println("登陸失敗");
            return "login";
        }
    }

    @RequestMapping(value="/register")
    public String register(UserForm user,Model model) {
        if(userService.register(user)) {
            System.out.println("註冊成功");
            return "login";
        } else {
            model.addAttribute("username",user.getUsername());//註冊失敗將原來使用者名稱重新顯示在文字框
            System.out.println("註冊失敗");
            return "register";
        }
    }
}

在pojo目錄下新建UserForm類檔案

package com.mike.pojo;

public class UserForm {
    private String username;
    private String password;
    private String newPassword;


    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 String getNewPassword() {
        return newPassword;
    }

    public void setNewPassword(String newPassword) {
        this.newPassword = newPassword;
    }
}

在service目錄下建立UserService介面及UserService介面的實現類UserServiceImpl

package com.mike.service;

import com.mike.pojo.UserForm;

public interface UserService {
    boolean login(UserForm user);
    boolean register(UserForm user);
}

package com.mike.service;

import com.mike.pojo.UserForm;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {
    public boolean login(UserForm user) {
        return "mike".equals(user.getUsername()) && "123".equals(user.getPassword());
    }

    public boolean register(UserForm user) {
        return "mike".equals(user.getUsername()) && "123".equals(user.getPassword());
    }
}

在jsp目錄下分別新建login.jsp

<%--
  Created by IntelliJ IDEA.
  User: mike
  Date: 2021/1/6
  Time: 13:03
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <%@page isELIgnored="false" %> <!--應為預設的servlet1.2 el表示式是關閉的,需要啟用-->
    <title>登陸</title>
</head>
<body>
<form action="<%request.getContextPath();%>/user/login" method="post" name="loginForm">
    <table>
        <tr>
            <td>姓名:</td>
            <td><input class="textSize" type="text" name="username"/></td>
        </tr>
        <tr>
            <td>密碼:</td>
            <td><input class="textSize" type="password" name="password"/></td>
        </tr>
        <tr>
            <td colspan="2" align="center">
                <input type="submit" value="登陸"/>
            </td>
        </tr>
    </table>
    ${messageError}
</form>
</body>
</html>

register.jsp

<%--
  Created by IntelliJ IDEA.
  User: gaoyong
  Date: 2021/1/6
  Time: 13:03
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <%@page isELIgnored="false" %> <!--應為預設的servlet1.2 el表示式是關閉的,需要啟用-->
    <title>註冊</title>
</head>
<body>
<form action="<%request.getContextPath();%>/user/register" method="post" name="registerForm">
    <table>
        <tr>
            <td>姓名:</td>
            <td><input class="textSize" type="text" name="username" value="${username}"/></td>
        </tr>
        <tr>
            <td>密碼:</td>
            <td><input class="textSize" type="password" name="password"/></td>
        </tr>
        <tr>
            <td>確認密碼:</td>
            <td><input class="textSize" type="password" name="newPassword"/></td>
        </tr>
        <tr>
            <td colspan="2" align="center">
                <input type="submit" value="註冊"/>
            </td>
        </tr>
    </table>
</form>
</body>
</html>

main.jsp

<%@ page import="com.mike.pojo.UserForm" %><%--
  Created by IntelliJ IDEA.
  User: gaoyong
  Date: 2021/1/6
  Time: 14:43
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陸成功頁面</title>
</head>
<body>
<% UserForm user = (UserForm)request.getSession().getAttribute("user");%>
<h1>當前登陸使用者為:<%= user.getUsername() %></h1>
</body>
</html>

注意:控制器中如 login(UserForm user,HttpSession session,Model model)方法中的引數,user會在當頁面的表單的name名和UserForm類中的屬性一致時,自動填充到該類,而model引數測試會將我們寫的資訊返回到jsp頁面
當我們訪問http://localhost:8080/index/register 方法會看到登錄檔單register.jsp,輸入mike,123,123 註冊成功會跳轉到登陸表單login.jsp,當我們再次輸入mike,123登陸成功後會跳轉到main.jsp會顯示當前登陸的使用者名稱