springmvc 概述
springmvc定義
基於spring的一個框架,實際上就是spring的一個模塊,專門是做web開發的,理解為servlet的升級。web開發底層是servlet,框架是在servlet基礎上面加入一些功能,讓開發更方便。
spring和springmvc對比
spring:spring是容器,ioc能夠管理對象,
使用< bean>,@Component,@Repository,@Service,@Controller 標籤
springmvc:能夠創建對象,放入到容器中(springmvc容器),spring容器中放的是控制器對象
springmvc簡要流程
我們要做的是 使用 @Controller 創建控制器對象 ,把對象放入到springmvc 容器中,把創建的對象作為控制器使用。這個控制器對象能夠接收用户的請求,顯示處理結果,就當作是一個servlet使用。
使用 @Controller 註解創建的是一個普通的對象 ,不是servlet,springmvc賦予了控制器對象一些額外的功能。
web開發底層是servlet,springmvc中有一個對象是servlet:DispatcherServlet(中央調度器)
DispatcherServlet:負責接收用户的所有請求,用户把請求給了DispatcherServlet,之後DispatcherServlet把請求轉發給我們的Controller對象,最後Controller對象處理請求。
開發步驟
index.jsp —> DispatcherServlet(中央調度器,類似servlet) ----> 轉發,分配給Controller對象(@Controller 註解創建的對象)
需求:用户在頁面發起一個請求,請求交給springmvc的控制器對象,並顯示請求的處理結果
實現步驟:
1 新建web maven工程
2 加入依賴,spring-webmvc依賴,間接把spring的依賴加入到項目中,jsp,servlet依賴
3 重點:在web.xml中註冊springmvc框架的核心對象 DispatcherServlet
1)DispatcherServlet叫做:中央調度器,是一個servlet,他的父類繼承 HttpServlet
2)DispatcherServlet也叫做:前端控制器(from controller)
3)DispatcherServlet:負責接收用户提交的請求,調用其他控制器對象,並把請求的處理結果顯示給用户
4 創建一個發起請求的頁面 index.jsp
5 創建控制器類
1)在類的上面加入@Controller註解,創建對象,並放到springmvc容器中
2) 在類中的方法上面加入@RequestMapping註解
6 創建一個作為結果的jsp,顯示請求的處理結果。
7 創建springmvc的配置文件(和spring的配置文件一樣)
1)聲明組件掃描器,指定@Controller註解所在的包名
2)聲明視圖解析器,幫助處理視圖
springmvc 開發流程:
1 發起some.do請求
2 tomcat (web.xml 從url-pattern知道 *.do 的請求給DispatcherServlet)
3 DispatcherServlet(根據spring.xml配置知道some.do,doSome()方法)
4 DispatcherServlet把some.do轉發給MyController.doSome()方法
5 框架執行doSome()把得到的ModelAndView進行處理,轉發到show.jsp
簡化流程:
some.do -> DispatcherServlet -> MyController
流程如圖:
創建好web項目後,在pom.xml中加入servlet和springmvc依賴
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--spring mvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
發送some.do請求的頁面 index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>第一個springmvc項目</p>
<p><a href="some.do">發起some.do請求</a></p>
</body>
</html>
核心配置文件 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--聲明:註冊springmvc的核心對象DispatcherServlet
需要在tomcat服務器啓動後,創建DispatcherServlet對象實例
為什麼要創建DispatcherServlet對象的實例呢?
因為在DispatcherServlet創建過程中,會同時創建springmvc容器對象,
讀取springmvc的配置文件,把這個配置文件中的對象都配置好,
當用户發起請求時就可以直接使用對象了。
servlet的初始化會執行init()方法,DispatcherServlet在init()中{
//創建容器,讀取配置文件
webApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc.xml");
//把容器對象放入到ServletContext中
getServletContext().setAttribute(key,ctx);
}
-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--自定義springmvc讀取文件的位置-->
<init-param>
<!--springmvc配置文件的位置屬性-->
<param-name>contextConfigLocation</param-name>
<!--指定自定義文件的位置-->
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--表示在tomcat啓動後,創建servlet對象
數字表示啓動後創建對象的順序,數值越小,tomcat創建對象越早,要求大於等於0的整數
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--
使用框架的時候,url-pattern可以使用兩種值
1.使用擴展名方式,語法 *.xxxx , xxxx時自定義擴展名。常用的方式 *.do, *.action, *.mvc等等
http://localhost:8080/myweb/some.do
http://localhost:8080?myweb/other.do
2.使用斜槓"/"
-->
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
tomcat啓動,創建DispatcherServlet對象,同時創建springmvc容器對象,讀取springmvc配置文件,
這裏配置文件的根地址 classpath = springmvc.xml
在spring.xml中聲明 組件掃描器 和 視圖解析器
springmvc.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"
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">
<!--聲明組件掃描器-->
<context:component-scan base-package="com.zh.controller"/>
<!--聲明 springmvc框架中的視圖解析器,幫助開發人員設置視圖文件的路徑-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前綴:視圖文件位置-->
<property name="prefix" value="/WEB-INF/view/"/>
<!--後綴:視圖文件的擴展名-->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
創建控制器類 MyController.java
package com.zh.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/*
* @Controller:創建處理器對象,對象放在springmvc容器中
*
* 能處理請求的都是控制器(處理器):MyController能處理請求,
* 叫做後端控制器(back controller)
* */
@Controller
public class MyController {
/*
* 處理用户提交的請求,springmvc中是使用方法來處理的。
* 方法是自定義的,可以有多種返回值,多種參數,方法名稱自定義
* */
/*
* 準備使用doSome方法處理some.do請求。
* @RequestMapping:請求映射,作用是把一個請求地址和一個方法綁定在一起。
* 一個請求指定一個方法處理。
* 屬性:1. value是一個String類型,表示請求的uri地址(這裏是:some.do)
* value值是唯一的,不能重複
* 説明:使用@RequestMapping修飾的方法叫做處理器方法或者控制器方法
* 可以處理請求,類似servlet中的doGet,doPost
* */
/*
* 返回值 ModelAndView 表示本次請求的處理結果
* model:數據,請求處理完後,要顯示給用户的數據
* view:視圖,比如jsp等
* */
@RequestMapping(value = "/some.do")
public ModelAndView doSome(){
//處理some.do請求,相當於service調用處理完成了
ModelAndView mv = new ModelAndView();
//添加數據,框架在請求的最後把數據放入到request作用域
//request.setAttribute("msg","歡迎使用....");
mv.addObject("msg","歡迎使用springmvc做web開發");
mv.addObject("fun","執行的是doSome方法");
//指定視圖,指定視圖的完整路徑
//框架對視圖執行的forward操作,request.getRequestDispather("/show.jsp").forward(...)
mv.setViewName("/show.jsp");
return mv;
}
//在springmvc.xml配置視圖解析器後,修改 setViewName()
@RequestMapping(value = {"/other.do","/second.do"})
public ModelAndView doOther(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","---------歡迎使用springmvc做web開發----------");
mv.addObject("fun","執行的是doOther方法");
//當配置了視圖解析器後,可以使用邏輯名稱(文件名),指定視圖
//框架會使用視圖解析器的 前綴 + 邏輯名稱 +後綴 組成完整路徑
mv.setViewName("other");
return mv;
}
}
對應的 show.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>show.jsp從request作用域獲取數據</h3><br/>
<h3>msg數據:${msg}</h3>
<h3>fun數據:${fun}</h3>
</body>
</html>
springmvc註解式開發
@RequestMapping 定義請求規則
放在類上面使用
/*
* @RequestMapping
* value:所有請求的公共部分,叫做模塊名稱
* 位置:在類的上面
* */
@Controller
@RequestMapping("/user")
//或者@RequestMapping("/test")
public class MyController {
@RequestMapping(value = "/some.do")
public ModelAndView doSome(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","歡迎使用springmvc做web開發");
mv.addObject("fun","執行的是doSome方法");
mv.setViewName("show");
return mv;
}
}
理解為在該方法在 user或者test模塊下
method 屬性 指定請求方式
@Controller
@RequestMapping("/test")
public class MyController {
/*
* @RequestMapping(value = "",method = )
* 屬性:method 表示請求的方式,它的值是RequestMethod類枚舉值
*
* get請求方式, method = RequestMethod.GET
* post請求方式,method = RequestMethod.POST
*
* */
//指定some.do用get請求獲取
@RequestMapping(value = "/some.do",method = RequestMethod.GET)
public ModelAndView doSome(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","歡迎使用springmvc做web開發");
mv.addObject("fun","執行的是doSome方法");
mv.setViewName("show");
return mv;
}
//指定other.do 用post請求獲取
@RequestMapping(value = "/other.do",method = RequestMethod.POST)
public ModelAndView doOther(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","---------歡迎使用springmvc做web開發----------");
mv.addObject("fun","執行的是doOther方法");
mv.setViewName("other");
return mv;
}
對應的index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>第一個springmvc項目</p>
<p><a href="test/some.do">發起some.do的get請求</a></p>
<br/>
<form action="test/other.do" method="post">
<input type="submit" value="post請求other.do">
</form>
<%-- <p><a href="user/other.do">發起other.do請求</a></p>--%>
</body>
</html>
處理器方法的參數
處理器方法可以包含以下四類參數,這些參數會在系統調用時由系統自動賦值,即程序員可以在方法中直接使用。
1 HttpServletRequest 請求
2 HttpServletResponse 應答
3 HttpSession 會話
4 請求中所攜帶的請求參數
前三類參數使用方式
@Controller
public class MyController {
@RequestMapping(value = "/some.do")
public ModelAndView doSome(HttpServletRequest request,
HttpServletResponse response,
HttpSession session){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","歡迎使用springmvc做web開發" + request.getParameter("name"));
mv.addObject("fun","執行的是doSome方法");
mv.setViewName("show");
return mv;
}
逐個參數接收
接收用户提交的參數:處理器(控制器)方法的形參名和請求中的參數必須一致
@Controller
public class MyController {
/*
* 逐個接收請求參數:
* 要求:處理器(控制器)方法的形參名和請求中的參數必須一致
* 同名的請求參數賦值給同名的參數
*
* 框架接收請求參數:
* 1 使用request對象接收請求參數
* String strName = request.getParameter("name");
* String strAge = request.getParameter("age");
* 2 springmvc框架通過dispatcherServlet 調用MyController的doSome方法
* 調用方法時,按名稱對應,把接收的參數賦值給形參 doSome(strName,Integer.valueOf(strAge))
* 框架會提供類型轉換的功能,把String轉換為 int ,long ,float ,double等
*
* */
@RequestMapping(value = "/some.do")
public ModelAndView doSome(String name,Integer age){
System.out.println("dosome方法的,name="+name+", age="+age);
ModelAndView mv = new ModelAndView();
mv.addObject("myname",name);
mv.addObject("myage",age);
mv.setViewName("show");
return mv;
}
}
對應的index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>提交參數給Controller</p>
<form action="some.do" method="post">
姓名:<input type="text" name="name"><br/>
年齡:<input type="text" name="age"><br/>
<input type="submit" value="提交參數">
</form>
<%-- <p><a href="user/other.do">發起other.do請求</a></p>--%>
</body>
</html>
注意:在提交請求參數的時候,get請求方式中文沒有亂碼;post請求方式中文有亂碼,需要使用過濾器處理亂碼問題。
//在web.xml配置過濾器
<!--註冊聲明過濾器,解決post請求亂碼的問題-->
<filter>
<filter-name>characterEncodingFilter</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>
<!--強制請求對象(HttpServletRequest)使用encoding編碼的值-->
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<!--強制應答對象(HttpServletResponse)-->
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<!--
/* : 表示強制所有的請求先通過過濾器處理
-->
<url-pattern>/rl-pattern>
</filter-mapping>
補充:springMVC 中的 M-model,V-view,C-controller
請求參數名和處理器方法的形參名不一樣,使用 @RequestParam 註解
首頁 index.jsp 的參數名是 iname 和 iage
<p>請求參數名和處理器方法的形參名不一樣</p>
<form action="other.do" method="post">
姓名:<input type="text" name="iname"><br/>
年齡:<input type="text" name="iage"><br/>
<input type="submit" value="提交參數">
</form>
控制器方法的 doOther 方法形參為 name 和 age
/*
* 請求參數名和處理器方法的形參名不一樣
* @RequestParam:定義在處理器方法的形參前面
* 屬性:1. value,請求參數名,可省略
* 2. required,是一個Boolean類型,默認為true,表示必須包含參數
* */
@RequestMapping(value = "/other.do")
public ModelAndView doOther(@RequestParam("iname" ) String name,
@RequestParam("iage") Integer age){
System.out.println("doOther方法的,name="+name+", age="+age);
ModelAndView mv = new ModelAndView();
mv.addObject("myname",name);
mv.addObject("myage",age);
mv.setViewName("show");
return mv;
}
但是有一個問題,當不通過首頁傳入參數,直接加載網址:http://localhost:8080/03_recevieparam/other.do ,將會報400的錯,説明請求端輸入有問題,如下圖
此時將@RequestParam標籤的屬性required改為 fslse,不用參數也可以顯示show.jsp。
當然我們希望required=true,作為前端限制。
public ModelAndView doOther(@RequestParam(value = "iname",required=false) String name,
@RequestParam(value = "iage",required = false) Integer age){
對象參數接收
將處理器方法的參數定義為一個對象,對象的屬性名要求和請求中參數名一致
先在vo包下定義一個Student 類
//保存請求參數值的普通類
public class Student {
//屬性值要和請求參數值一樣
private String name;
private int age;
public Student() { System.out.println("---------Student的無參構造方法--------"); }
public String getName() {return name;}
public void setName(String name) {System.out.println("setName= "+name);this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {System.out.println("setAge= "+age);this.age = age;}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
主頁index.jsp
<p>使用java對象接收參數</p>
<form action="object.do" method="post">
姓名:<input type="text" name="name"><br/>
年齡:<input type="text" name="age"><br/>
<input type="submit" value="提交參數">
</form>
處理器方法
/*
* 處理器方法的形參是java對象,這個對象的屬性名要求和請求中參數名一致
* 框架會創建形參的java對象,給屬性賦值。請求中的參數是name,框架會調用setName()完成賦值
* */
@RequestMapping(value = "/object.do")
public ModelAndView doObject(Student student){
System.out.println("doObject方法的,name="+student.getName()+", age="+student.getAge());
ModelAndView mv = new ModelAndView();
mv.addObject("myname",student.getName());
mv.addObject("myage",student.getAge());
mv.addObject(student);
mv.setViewName("show");
return mv;
}
頁面結果
後台結果
處理器方法返回值
ModelAndView 返回值
若處理器方法處理完後,需要跳轉到其他資源,且又要在跳轉的資源間傳遞數據,此時處理器方法返回 ModelAndView 比較好。當然,若要返回 ModelAndView,則處理器方法中需要定義 ModelAndView對象。
返回值 String ,表示邏輯視圖名稱或完整視圖路徑
@Controller
public class MyController {
/*
* 處理器方法返回String,表示邏輯視圖名稱,需要配置視圖解析
* */
@RequestMapping(value = "/returnString-view.do")
public String doReturnView(HttpServletRequest request,String name, Integer age) {
System.out.println("dosome方法的,name=" + name + ", age=" + age);
//手動添加數據到request作用域
request.setAttribute("myname",name);
request.setAttribute("myage",age);
/*
* show:邏輯視圖名稱
* 框架對視圖執行forward轉發操作
* */
return "show";
}
//處理器方法返回 String,表示完整視圖路徑,此時不能配置視圖解析器
@RequestMapping(value = "/returnString-view2.do")
public String doReturnView2(HttpServletRequest request,String name, Integer age) {
System.out.println("---doReturnView2方法---,name=" + name + ", age=" + age);
//手動添加數據到request作用域
request.setAttribute("myname",name);
request.setAttribute("myage",age);
/*
* 完整視圖路徑,項目中不能配置視圖解析器
* 框架對視圖執行forward轉發操作
* */
return "WEB-INF/view/show.jsp";
}
}
返回值 void ,瞭解
void:不能表示數據,也不能表示視圖。在處理ajax的時候,可以使用void返回值。通過HttpServletResponse輸出數據。響應ajax請求。ajax請求服務器端返回的就是數據,和視圖無關。
返回值 object 對象
object:例如String,Integer,Map,List,Student 等等都是對象,對象有屬性,屬性就是數據。所以返回 object 表示數據,和視圖無關。可以使用對象表示的數據,響應ajax請求。
現在做 ajax,主要使用 json的數據格式。
面試:springmvc開發中,返回值是object類型,如何轉換為 json ?實現步驟:
1 加入處理json的工具庫的依賴,springmvc默認使用的jackson
pom.xml 加入jackson依賴
<!--jackson依賴-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
2 在springmvc配置文件之間加入 <mvc:annotation-driven> 註解驅動
主配置文件 springmvc.xml 加入:
<!--@ResponseBody註解驅動-->
<mvc:annotation-driven/>
3 在處理器方法的上面加上 @ResponseBody
3 在處理器方法的上面加上 @ResponseBody
控制器方法 MyController.java
//處理器方法返回一個Student,通過框架轉為json,響應ajax請求
//@ResponseBody 作用:把處理器方法返回對象轉為json後,通過HttpServletResponse輸出給瀏覽器
@ResponseBody
@RequestMapping(value = "returnStudentJson.do")
public Student doStudentJsonObject(String name,Integer age){
Student student = new Student();
student.setName("lisi");
student.setAge(10);
return student; //會被框架轉為json
}
當返回值是多個參數(用的比較普遍),返回類型改為List集合,其他不變
@RequestMapping(value ="returnStudentJsonArray.do" )
@ResponseBody
public List<Student> doStudentJsonObjectArray(String name,Integer age){
List<Student> list = new ArrayList<>();
Student student = new Student();
student.setName("wangwu");
student.setAge(22);
list.add(student);
student = new Student();
student.setName("tianmao");
student.setAge(10);
list.add(student);
return list;
}
前端頁面 index.jsp ,返回 json 格式為:[{“name”:“wangwu”,“age”:22},{“name”:“tianmao”,“age”:10}]
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-3.5.1.js"></script>
<script type="text/javascript">
$(function () {
$("button").click(function () {
// alert("button click");
$.ajax({
// url:"returnVoid-ajax.do",
// url:"returnStudentJson.do",
url:"returnStudentJsonArray.do",
data:{
name:"zhangsan",
age:20
},
type:"post",
dataType:"json",
success:function(resp) {
// alert(resp.name+" "+resp.age);
//[{"name":"wangwu","age":22},{"name":"tianmao","age":10}]
$.each(resp,function (i,n) {
alert(n.name+" "+n.age);
})
}
})
})
})
</script>
</head>
處理器方法返回的是 String,表示數據,不是視圖
/*
* 處理器方法返回的是String,String表示數據的,不是視圖。
* 區分返回值類型String是數據,還是視圖,看看有沒有@ResponseBody註解
* 如果有@ResponseBody註解,返回String就是數據,反之就是視圖
* */
@ResponseBody
public String doStringData(String name,Integer age){
return "返回對象,表示數據";
}
springmvc 處理器方法返回 object,可以轉為 json輸出到瀏覽器,響應 ajax 的內部原理
1 <mvc:annotation-driven> 註解驅動
註解驅動實現的功能是:完成java對象到 json,xml,test,二進制等數據格式的轉換
HttpMessageConverter接口:消息轉換器
功能:定義了java轉json,xml等數據格式的方法。這個接口有很多實現類
這些實現類完成了java對象到json,Java對象到xml,Java對象到二進制數據的轉換
2 HttpMessageConverter接口的兩個方法是:控制器類把結果輸出給瀏覽器時使用的
boolean canWrite(Class<?> var1, @Nullable MediaType var2);
void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3)
1) canWrite:檢查處理器方法返回值,能不能轉為var2的數據格式
2) write:把處理器方法的返回值對象,調用jackson中的ObjectMapper轉為json字符串
3 ResponseBody 註解
放在處理器方法的上面,通過HttpServletResponse輸出結果,響應ajax請求
解讀中央調度器 < url-pattern/ >
1 .do
在沒有特殊要求的情況下,springmvc 的中央調度器 DispatcherServlet 的< url-pattern/ >常使用後綴匹配方式,如寫為 *.do 或者 *.action , *.mvc 等
2 /
可以寫為 / ,因為DispatcherServlet會將向靜態資源的獲取請求,例如 .css .js .jpg .png 等資源的獲取請求,作為是一個普通的Controller請求。中央調度器會調用處理器映射器為其查找相應的處理器。當然也是找不到的,所以在這種情況下,所有的靜態資源獲取請求也均會報404錯誤。
發起的請求是由哪些服務器處理的:
http: //localhost:8080/05_url_pattern/index.jsp tomcat
http: //localhost:8080/05_url_pattern/images/1.jpg tomcat
http: //localhost:8080/05_url_pattern/html/test.html tomcat
http: //localhost:8080/05_url_pattern/some.do springmvc框架(DispatcherServlet)
tomcat本身能處理靜態資源的訪問,像html,圖片,js文件等都是靜態資源
tomcat的web.xml文件有一個 servlet 名稱為 default,在服務器啓動時創建。如下:
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern> // "/" 表示靜態資源和未映射的請求都給這個default處理
</servlet-mapping>
這個名叫 default 的 servlet 作用:
1 處理靜態資源
2 處理未映射到其它servlet的請求
使用 ” / “ 後,無法訪問靜態資源,可以訪問動態資源
// web.xml
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--
使用框架的時候,url-pattern可以使用兩種方式
1.使用擴展名方式,語法 *.xxxx , xxxx時自定義擴展名。常用的方式 *.do, *.action, *.mvc等等
http://localhost:8080/myweb/some.do
http://localhost:8080?myweb/other.do
2.使用斜槓 "/"
當你的項目使用了 / ,它會替換 tomcat 中的 default.
導致所有的靜態資源都給DispatcherServlet處理,默認情況下DispatcherServlet沒有處理靜態資源的能力,
沒有控制器對象能處理靜態資源的訪問,所以靜態資源(html,js,圖片,css)都是404
動態資源some.do可以訪問,原因時我們程序中有MyController控制器對象,能處理some.do請求
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
讓靜態資源可以訪問的兩種方式
1 使用 < mvc:default-servlet-handler > 和 < mvc:annotation-driven/ >
// springmvc.xml
<!--@ResponseBody註解驅動-->
<mvc:annotation-driven/>
<!--第一種處理靜態資源的方式:<mvc:default-servlet-handler/>
需要在springmvc配置文件加入 <mvc:default-servlet-handler>
原理是:加入這個標籤後,框架會創建控制器對象(類似自己創建的MyController),
這個對象可以把接收到的請求轉發給tomcat的名字叫default的servlet
-->
<mvc:default-servlet-handler/>
2 使用 < mvc:resources /> 需要掌握
在 spring3.0 版本後,spring定義了專門用來處理靜態資源訪問請求的處理器 ResourceHttpRequestHandler。並且添加了< mvc:resources />標籤,專門用於解決資源無法訪問問題。需要在springmvc配置文件中添加如下形式的配置:
//springmvc.xml
<!--第二種處理靜態資源的方式
mvc:resources加入後框架會創建 ResourceHttpRequestHandler這個處理器對象
讓這個對象處理靜態資源的訪問,不依賴tomcat服務器。
mapping:訪問靜態資源的uri地址,使用通配符 **
location:靜態資源在你的項目中的目錄位置
-->
<mvc:resources mapping="/images/**" location="/images/" />
<mvc:resources mapping="/html/**" location="/html/" />
<mvc:resources mapping="/js/**" location="/js/" />
為了方便,一般把靜態資源統一放在 static 文件夾下
所以一個標籤語句就可以指定多個靜態資源的訪問路徑(重點):
<mvc:resources mapping="/static/**" location="/static/" />
地址分類
1 絕對地址:帶有協議名稱的,例如:http://www/baidu.com
2 相對地址,沒有協議開頭的,例如:user/some.do,/user/some.do
相對地址不能獨立使用,必須有一個參考地址。通過參考地址+相對地址本身才能指定資源
3 參考地址
在你的頁面中,訪問地址不加 " / "
訪問地址:http: //localhost:8080/06_path/index.jsp
路徑:http: //localhost:8080/06_path/
資源:index.jsp
在index.jsp發起 user/some.do請求,訪問地址變為http: //localhost:8080/06_path/test/some.do
在你的地址沒有斜槓開頭,例如:user/some.do,當你點擊鏈接時,訪問地址就是當前頁面加上鍊接的地址
http: //localhost:8080/06_path/ + user/some.do
在你的頁面中,訪問地址加 " / "
訪問地址:http: //localhost:8080/06_path/index.jsp
路徑:http: //localhost:8080/06_path/
資源:index.jsp
點擊 /user/some.do,訪問地址變為:http: //localhost:8080/test/some.do
參考地址是你的服務器地址,也就是http: //localhost:8080
如果你的資源不能訪問,加上:${pageContext.request.contextPath},修改如下
//index.jsp
<body>
<p>第一個springmvc項目</p>
<p><a href="/test/some.do">發起/test/some.do的get請求</a></p>
<br/>
</body>
//修改為
<body>
<p>第一個springmvc項目</p>
<p><a href="${pageContext.request.contextPath}/test/some.do">發起test/some.do的get請求</a></p>
<br/>
</body>
則在網頁訪問:http: //localhost:8080/06_path/index.jsp 時,網頁源碼如下
此時點擊請求,動態獲取項目地址(06_path),頁面正確顯示如下:
springmvc核心技術補充鏈接
springmvc核心技術補充