今天來嘗試一下搭建基於SpringMVC的RESTful標準的後端服務。html
首先,什麼是MVC?M-model,模型,指業務數據層,具體一點就是業務邏輯與數據庫的交互;V-view,視圖,用來展現數據,傳統SpringMVC中控制器有返回類型ModelAndView,即返回含有數據模型與頁面視圖的jsp文件;C-controller,控制器,一般負責處理與用戶間的交互,控制從數據庫取數與返回結果到用戶等。前端
那麼,什麼是REST風格的服務呢?REST(Representational State Transfer),中文能夠叫表述性狀態轉移,有如下幾個特色java
簡單來講,傳統的MVC框架,後端和前端是部署在一塊兒的,服務器接受請求,去數據庫(緩存實質也是非關係型的鍵值對數據庫)查詢而後計算,而後和jsp進行組裝渲染,直接返回一個完整的html給瀏覽器。而RESTful的結構下,前端和後端是能夠分離部署的,瀏覽器訪問一個頁面,前端根據須要向後端發送HTTP請求,後端接收請求而後一樣查詢數據庫再計算,把結果封裝爲JSON報文後返回給前端,前端把數據組裝到靜態頁面中,生成最終展現給用戶的頁面。web
從我的在開發中的理解,RESTful相比之下有如下幾個優勢:ajax
下面正式開始環境的搭建,由於主要是講環境搭建,一下配置內容分析先不寫了,留到深刻研究spring以後spring
首先編輯pom.xml,把須要的jar包先弄進來,若是沒有自動下載的話,手動在工程項目上右鍵maven->update project,注意要把forcre那行勾上。數據庫
列表能夠參考下面這個,這裏建議spring這樣一個系列的包的版本號統一在最上方以參數寫入,便於集體版本替換,這點在企業開發中也是很是經常使用的。express
<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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.graywind</groupId> <artifactId>webdemo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <!-- springframe 版本控制 --> <spring.version>4.1.6.RELEASE</spring.version> </properties> <dependencies> <!-- springframe start --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</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-oxm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</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-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!-- springframe end --> <!--log4j日誌包 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- JUnit單元測試工具 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> </dependency> <!-- aspectJ AOP 織入器 --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version> </dependency> <!-- jstl --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- JSON: jackson --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.5.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.5.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.5.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.jr</groupId> <artifactId>jackson-jr-all</artifactId> <version>2.5.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.46</version> </dependency> </dependencies> <build> <plugins> <!-- define the project compile level --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
而後修改些項目屬性,右鍵項目properties->prject facts肯定設置以下。若web module不是3.0可把勾去掉,應用後再修改到3.0.apache
而後到deployment assembly,設置以下json
修改web.xml以下,這裏有兩個配置文件的路徑是以classpath開頭,根據上方的設置classpath會從WEB-INF/classes開始尋找,而src/main/java和src/main/resources下的內容會被裝配至該路徑下。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>mybatis</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- springmvc配置 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <description>spring mvc 配置文件</description> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.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> <description>字符集過濾器</description> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <description>字符集編碼</description> <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> <!--設置log4j的配置文件位置 --> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j.properties</param-value> </context-param> <!--使用監聽加載log4j的配置文件 --> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> </web-app>
如今添加application.xml和springmvc.xml以及log4j.properties至resources目錄下
<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "> <!-- 啓用註解掃描,並定義組件查找規則 ,除了@controller,掃描全部的Bean --> <context:component-scan base-package="webdemo.*"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> </beans>
<?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 http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"> <!-- 啓用註解掃描,並定義組件查找規則 ,mvc層只負責掃描@Controller、@ControllerAdvice --> <!-- base-package 若是多個,用「,」分隔 --> <context:component-scan base-package="webdemo.*" use-default-filters="false"> <!-- 掃描@Controller --> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <!-- 控制器加強,使一個Contoller成爲全局的異常處理類,類中用@ExceptionHandler方法註解的方法能夠處理全部Controller發生的異常 --> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" /> </context:component-scan> <!-- 會自動註冊RequestMappingHandlerMapping與RequestMappingHandlerAdapter兩個Bean, 這是SpringMVC爲@Controllers分發請求所必需的,並提供了數據綁定支持、@NumberFormatannotation支持、 @DateTimeFormat支持、@Valid支持、讀寫XML的支持和讀寫JSON的支持等功能。 --> <mvc:annotation-driven /> <!-- 使用默認的Servlet來響應靜態文件 --> <mvc:default-servlet-handler /> <!-- 視圖解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 前綴 --> <property name="prefix"> <value>/WEB-INF/pages/</value> </property> <!-- 後綴 --> <property name="suffix"> <value>.jsp</value> </property> </bean> <bean id="stringConverter" class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/plain;charset=UTF-8</value> </list> </property> </bean> <!-- 輸出對象轉JSON支持 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> <value>text/plain;charset=UTF-8</value> <value>application/json;charset=UTF-8</value> </list> </property> </bean> </list> </property> </bean> </beans>
### set log levels ###
log4j.rootLogger = debug,stdout,D,E
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = ${catalina.home}/logs/webdemo-info.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = INFO
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =${catalina.home}/logs/webdemo-error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
${catalina.home}表示日誌文件會產生到tomcat的文件目錄下
而後添加controller與bean
package webdemo.hello; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/") public class UserController { private static final Logger log = Logger.getLogger(UserController.class); @RequestMapping("/hello") public String hello(){ return "hello"; } @RequestMapping(value = "/user/{id}", method = RequestMethod.GET, produces = "application/json") public User getUser(@PathVariable("id") int id){ log.info("get user " + id); User user = new User(); user.setId(id); user.setName("Hello"); return user; } @RequestMapping(value = "/userlist", method = RequestMethod.GET, produces = "application/json") public List<User> getUserlist(){ System.out.println("get userlist"); List<User> list = new ArrayList<User>(); for(int i=1;i<10;i++){ User user = new User(); user.setId(i); user.setName("Hello"); list.add(user); } return list; } }
package webdemo.hello; public class User { private String name; private int id; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } }
如今啓動服務器,測試下接口,由於我把server設置那裏的path去掉了,因此直接輸入IP與端口
如今網頁上顯示的就是json報文了,基本的環境也就搭建完成了。可是以網站開發角度來講,後續還有不少須要擴展的地方,好比權限控制過濾器,ajax報文的組裝,錯誤控制,日誌切面等等,後續會進一步在這個基礎上擴展。