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會顯示當前登陸的使用者名稱