(五)最簡單的springMVC后臺(tái)程序
這一小節(jié)碍庵,我們會(huì)搭建一個(gè)最簡單的springMVC后臺(tái)服務(wù)程序炕淮,初步了解這個(gè)框架的開發(fā)流程
我們需要使用 (四)創(chuàng)建的Maven Web 工程 中創(chuàng)建的那個(gè)工程源碼。
1.添加依賴包
我們是基于maven來管理項(xiàng)目的枫慷,所以添加依賴包只需要修改pom.xml
文件即可膛腐。
從Maven倉庫查找包獲取依賴配置遗增,在 (二)創(chuàng)建maven工程 中有詳細(xì)介紹张咳,這里不再贅述帝洪。
添加完依賴包的pom.xml
文件如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.springdemo</groupId>
<artifactId>springstart</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>springstart Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>4.3.13.RELEASE</spring.version>
<jackson.version>2.9.5</jackson.version>
<security.verison>4.1.3.RELEASE</security.verison>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<!-- spring start -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${security.verison}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${security.verison}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${security.verison}</version>
</dependency>
<!-- spring end -->
<!-- mysql start -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- mysql end -->
<!-- bonecp start -->
<dependency>
<groupId>com.jolbox</groupId>
<artifactId>bonecp</artifactId>
<version>0.8.0.RELEASE</version>
</dependency>
<dependency>
<groupId>com.jolbox</groupId>
<artifactId>bonecp-spring</artifactId>
<version>0.8.0.RELEASE</version>
</dependency>
<!-- bonecp end -->
<!-- mybatis start -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!-- mybatis end -->
<!-- redis start-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.0.8.RELEASE</version>
</dependency>
<!-- redis end -->
</dependencies>
<build>
<finalName>springstart</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
修改完成之后,保存pom.xml
文件脚猾,然后就會(huì)有個(gè)過程葱峡,如果本地沒有需要的包,maven會(huì)從中央倉庫拉取這個(gè)包婚陪,這個(gè)跟網(wǎng)速有關(guān),需要一定時(shí)間频祝。
如果要問泌参,如何得知需要添加這些依賴包呢?其實(shí)就是邊用邊發(fā)現(xiàn)缺了常空,再查找添加上沽一,慢慢的,配置就完善了漓糙。
2.配置web.xml
在src/main/webapp/WEB-INF
下面有一個(gè)web.xml
文件铣缠,這個(gè)是springMVC框架的webapp的主要配置文件
在上一節(jié)中我們已經(jīng)講過了如何把a(bǔ)pp放到tomcat下運(yùn)行,這里我們不再講,有不清楚的可以看看上一節(jié)(四)創(chuàng)建的Maven Web 工程
首先蝗蛙,springMVC的一個(gè)核心配置
<servlet>
<servlet-name>springStart</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
其中的 <servlet-name>springStart</servlet-name>
這個(gè)是設(shè)置servlet的名字蝇庭,這個(gè)隨便設(shè)定,后面會(huì)用到
然后
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
這一段捡硅,是springMVC的運(yùn)行核心
我們先說一下哮内,什么是 servlet,簡單的說壮韭,servlet就是對用戶請求和返回?cái)?shù)據(jù)的一個(gè)調(diào)度器北发。
Tomcat是一個(gè)servlet容器,將用戶的請求轉(zhuǎn)給servlet處理喷屋,將servlet返回的數(shù)據(jù)返給用戶琳拨。
而DispatcherServlet就是springMVC實(shí)現(xiàn)的一個(gè)servlet,工作流程大致如下:
最簡單的一個(gè)流程說明:用戶發(fā)出的請求屯曹,通過
DispatcherServlet
過濾狱庇,根據(jù)請求分發(fā)到不同的控制器,控制器將不同的請求分發(fā)到不同的業(yè)務(wù)邏輯來處理是牢,最后將數(shù)據(jù)逐層返回給用戶僵井。后面我會(huì)單獨(dú)寫文章來講一講Servlet,有興趣的同學(xué)可以關(guān)注我驳棱。
上面這個(gè)流程批什,后面我們可以逐漸實(shí)現(xiàn)、體會(huì)社搅。
Servlet配置之后驻债,還需要配置一個(gè)
<servlet-mapping>
<servlet-name>springStart</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
url-pattern
表示匹配的url規(guī)則,具體規(guī)則先不細(xì)講形葬,我們這里使用/
表示匹配所有url請求合呐,所有到springStart的請求都要使用DispatcherServlet
處理。
這樣笙以,我們修改后的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>
<servlet>
<servlet-name>springStart</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springStart</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
把工程加載到tomcat淌实,然后啟動(dòng)tomcat,從Console打印窗口猖腕,可以看到運(yùn)行情況
可以看到拆祈,有錯(cuò)誤發(fā)生,最主要的一句就是
java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/springStart-servlet.xml]
找不到/WEB-INF/springStart-servlet.xml
這個(gè)文件倘感,這個(gè)也是springMVC的一個(gè)主要配置文件
可以看出放坏,默認(rèn)是在/WEB-INF
目錄下找這個(gè)文件,文件名的格式就是servlet_name-servlet.xml
那么我們就在這個(gè)目錄下建一個(gè)這個(gè)文件老玛,這個(gè)文件有一些固定的格式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
</beans>
再運(yùn)行tomcat看看淤年,沒有報(bào)錯(cuò)钧敞,我們在瀏覽器輸入 http://localhost:8080/springstart/ 可以訪問到我們的index.jsp,說明服務(wù)正常跑起來了麸粮。
前面我們說了溉苛,DispatcherServlet
會(huì)過濾處理所有的請求,而我們設(shè)置的過濾條件是/
豹休,就是所有請求都會(huì)被處理炊昆,都會(huì)發(fā)送到控制層,為什么我們這里還沒有寫所謂的控制層威根,就已經(jīng)可以訪問頁面了呢
我的理解凤巨,DispatcherServlet
只會(huì)控制對/WEB-INF
下面的頁面的訪問,對于/webapp下的訪問無法控制洛搀,在上一小節(jié)中我們沒有配置servlet敢茁,也能訪問到index.jsp。
好了留美,現(xiàn)在我們的基礎(chǔ)框架已經(jīng)搭建起來了彰檬,接下來,我們進(jìn)行各種配置和功能添加
修改servlet配置文件
首先谎砾,我們不一定把servlet_name-servlet.xml
放在/WEB-INF/下面逢倍,我們更傾向于把所有配置文件放到一個(gè)特定目錄下,同時(shí)景图,我們也不想就非得叫這個(gè)名字较雕,想叫一下其他名字
一般,我們把配置文件放到src/main/resources
下面挚币,我們在這個(gè)目錄下創(chuàng)建一個(gè)文件夾config亮蒋,后面我們所有的配置文件都放在這里。
復(fù)制servlet_name-servlet.xml到config下妆毕,改個(gè)名字又谋,比如叫mymvc.xml,目錄結(jié)構(gòu)如下圖
然后抡驼,修改web.xml中DispatcherServlet的配置
<servlet>
<servlet-name>springStart</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/mymvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
其中新增的
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/mymvc.xml</param-value>
</init-param>
就是指定servlet的配置文件放在哪里薇组,叫什么名字队腐。
classpath
默認(rèn)情況下指向的是WEB-INF/classes
這個(gè)路徑,但是我們的WEB-INF下面沒有這個(gè)classes啊薪前。润努。。這個(gè)指的編譯之后的路徑
首先序六,把servlet_name-servlet.xml
刪了任连,我們試一下新創(chuàng)建的mymvc.xml
有作用沒有蚤吹。
把剛才運(yùn)行的tomcat停了例诀,重新運(yùn)行一次随抠,待運(yùn)行完成后,在瀏覽器里刷新剛才那個(gè)地址http://localhost:8080/springstart/繁涂,頁面依然顯示出來拱她,說明配置有效。
這個(gè)時(shí)候扔罪,我們打開tomcat的安裝目錄秉沼,依次打開webapps\springstart\WEB-INF
,可以看到矿酵,WEB-INF
下面有classes
目錄唬复,而且classes
下面有config
目錄,classpath
指向的就是這個(gè)classes
全肮,目前我們沒有寫java代碼敞咧,所以這里面還沒有class文件,后面會(huì)有的辜腺。
添加控制器
控制器實(shí)際就是對用戶訪問url的響應(yīng)控制休建,簡單來說,用戶輸入 http://localhost:8080/springstart/firstpage 和輸入 http://localhost:8080/springstart/secondpage 應(yīng)該得到不同的響應(yīng)评疗。
控制器(controller)這部分比較模式化测砂,也就是有固定結(jié)構(gòu),在MVC框架下百匆,controller本來的定位就是一個(gè)簡單的接受數(shù)據(jù)返回?cái)?shù)據(jù)的功能砌些,具體數(shù)據(jù)處理,都在業(yè)務(wù)邏輯層胧华。
首先寄症,在src/main/java下面,創(chuàng)建一個(gè)包 com.springstart.controller矩动,然后有巧,在這個(gè)包里面,創(chuàng)建一個(gè)java類悲没,DemoController.class,具體代碼如下:
package com.springstart.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class DemoController {
@RequestMapping(value="/hello",method=RequestMethod.GET)
public String MyFirstController(){
System.out.println("some one call MyFirstController");
return "hello";
}
}
這段代碼的意思很簡單篮迎,就是返回一個(gè)字符串hello,只是多了一些注解示姿,我們來解釋一下這些注解(關(guān)于java的注解請自行百度一下)甜橱。
@Controller
這個(gè)就是告訴spring,我這個(gè)類栈戳,是一個(gè)controller岂傲,實(shí)際上,這個(gè)就是讓這個(gè)類成為一個(gè)bean子檀,被會(huì)spring自動(dòng)掃描的時(shí)候處理為一個(gè)bean镊掖,但是特定的controller有一些特別的配置乃戈,同樣的注解還有@Service,@Component等亩进。
@RequestMapping
用來處理請求地址映射,看我們這里寫的
@RequestMapping(value="/hello",method=RequestMethod.GET)
這個(gè)就是一個(gè)最常用的方式症虑,value后面跟的就是地址映射,value="/hello"的意思就是归薛,我們這個(gè)方法處理springstart/hello 這個(gè)URI谍憔,method表示請求的方法,如GET
主籍,POST
习贫,PUT
,DELETE
等千元,如果不添加method沈条,那么就表示對所有方法進(jìn)行處理,添加了指定method诅炉,就只處理這個(gè)類型的請求蜡歹。
這個(gè)注解同時(shí)還可以放在類上面,例如:
@Controller
@RequestMapping(value="/user")
public class DemoCon {
@RequestMapping(value="/name",method=RequestMethod.POST)
public String addUserName(){
return null;
}
@RequestMapping(value="/id",method=RequestMethod.POST)
public String addUserId(){
return null;
}
}
這個(gè)demo涕烧,我們給類DemoCon加了@RequestMapping(value="/user")
注解月而,表示DemoCon整個(gè)類處理 /user的地址請求,下面每個(gè)方法的地址請求前需要加上/user
比如方法addUserName處理的就是 /user/name
好了议纯,控制器寫好了父款,我們需要使用它,得增加一些配置瞻凤。
這個(gè)配置要寫到mymvc.xml
中憨攒,之前,我們這個(gè)文件是空的阀参,寫點(diǎn)配置進(jìn)去之后
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:component-scan base-package="com.springstart.*"></context:component-scan>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
component-scan
這個(gè)的意思就是去掃描base-package
指定位置中的關(guān)于bean的注解肝集,比如@Component,@Service蛛壳,@Controller杏瞻,@Repository等,而base-package
一般就是包路徑
通過component-scan
之后衙荐,我們的controller才可以使用
下面的org.springframework.web.servlet.view.InternalResourceViewResolver
這個(gè)可以簡單的理解為視圖處理器捞挥,前面我們寫的controller返回的是一個(gè)字符串 hello,但是忧吟,這不是真正的把字符串返回給頁面砌函,是告訴servlet返回的是一個(gè)叫hello的視圖,具體這個(gè)視圖如何解釋呢溜族,就使用這個(gè)InternalResourceViewResolver
,下面的參數(shù)配置告訴了我們
prefix
是前綴讹俊,就是視圖的路徑
suffix
是后綴雏掠,就是視圖的后綴
兩個(gè)結(jié)合起來,我們的hello變成了/WEB-INF/pages/hello.jsp
,servlet就把這個(gè)頁面返給瀏覽器劣像。
在/WEB-INF/下創(chuàng)建一個(gè)pages目錄,放一個(gè)hello.jsp進(jìn)去摧玫,hello.jsp的源碼如下:
<html>
<body>
<h2>This is my HELLO!!</h2>
</body>
</html>
這樣耳奕,/WEB-INF/ 的目錄結(jié)構(gòu)如下:
好了,我們把tomcat運(yùn)行起來诬像,在瀏覽器輸入 http://localhost:8080/springstart/hello
可以看到 This is my HELLO!! 正確的顯示到了頁面上屋群。
但是,如果我們像index.jsp一樣坏挠,自己通過鏈接http://localhost:8080/springstart/hello.jsp去訪問hello.jsp芍躏,是無法訪問的,提示404錯(cuò)誤降狠,這是框架對資源的保護(hù)对竣,WEB-INF 下的資源,不能直接訪問榜配。
好了否纬,最簡單的一個(gè)springMVC框架搭建好了,后面我們繼續(xù)往里面添加各種功能蛋褥。
本次生成的工程代碼在 sprintStart github springStart_basic_1 目錄下临燃,請自行下載