今天来尝试一下搭建基于SpringMVC的RESTful标准的后端服务。
首先,什么是MVC?M-model,模型,指业务数据层,具体一点就是业务逻辑与数据库的交互;V-view,视图,用来展示数据,传统SpringMVC中控制器有返回类型ModelAndView,即返回含有数据模型与页面视图的jsp文件;C-controller,控制器,通常负责处理与用户间的交互,控制从数据库取数与返回结果到用户等。
那么,什么是REST风格的服务呢?REST(Representational State Transfer),中文可以叫表述性状态转移,有以下几个特点
简单来说,传统的MVC框架,后端和前端是部署在一起的,服务器接受请求,去数据库(缓存实质也是非关系型的键值对数据库)查询然后计算,然后和jsp进行组装渲染,直接返回一个完整的html给浏览器。而RESTful的结构下,前端和后端是可以分离部署的,浏览器访问一个页面,前端根据需要向后端发送HTTP请求,后端接收请求然后同样查询数据库再计算,把结果封装为JSON报文后返回给前端,前端把数据组装到静态页面中,生成最终展示给用户的页面。
从个人在开发中的理解,RESTful相比之下有以下几个优点:
下面正式开始环境的搭建,因为主要是讲环境搭建,一下配置内容分析先不写了,留到深入研究spring之后
首先编辑pom.xml,把需要的jar包先弄进来,如果没有自动下载的话,手动在工程项目上右键maven->update project,注意要把forcre那行勾上。
列表可以参考下面这个,这里建议spring这样一个系列的包的版本号统一在最上方以参数写入,便于集体版本替换,这点在企业开发中也是非常常用的。
<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.0modelVersion> <groupId>com.graywindgroupId> <artifactId>webdemoartifactId> <version>0.0.1-SNAPSHOTversion> <packaging>warpackaging> <properties> <spring.version>4.1.6.RELEASEspring.version> properties> <dependencies> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-coreartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-webartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-oxmartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-txartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-jdbcartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-webmvcartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-aopartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-context-supportartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-testartifactId> <version>${spring.version}version> dependency> <dependency> <groupId>log4jgroupId> <artifactId>log4jartifactId> <version>1.2.17version> dependency> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>4.10version> dependency> <dependency> <groupId>org.aspectjgroupId> <artifactId>aspectjweaverartifactId> <version>1.8.9version> dependency> <dependency> <groupId>javax.servletgroupId> <artifactId>jstlartifactId> <version>1.2version> dependency> <dependency> <groupId>com.fasterxml.jackson.coregroupId> <artifactId>jackson-annotationsartifactId> <version>2.5.0version> dependency> <dependency> <groupId>com.fasterxml.jackson.coregroupId> <artifactId>jackson-coreartifactId> <version>2.5.0version> dependency> <dependency> <groupId>com.fasterxml.jackson.coregroupId> <artifactId>jackson-databindartifactId> <version>2.5.0version> dependency> <dependency> <groupId>com.fasterxml.jackson.jrgroupId> <artifactId>jackson-jr-allartifactId> <version>2.5.0version> dependency> <dependency> <groupId>com.alibabagroupId> <artifactId>fastjsonartifactId> <version>1.2.46version> dependency> dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.pluginsgroupId> <artifactId>maven-compiler-pluginartifactId> <version>2.3.2version> <configuration> <source>1.8source> <target>1.8target> configuration> plugin> plugins> build> project>
然后修改些项目属性,右键项目properties->prject facts确定设置如下。若web module不是3.0可把勾去掉,应用后再修改到3.0.
然后到deployment assembly,设置如下
修改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>mybatisdisplay-name>
<welcome-file-list>
<welcome-file>index.jspwelcome-file>
welcome-file-list>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicationContext.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<description>spring mvc 配置文件description>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
<filter>
<description>字符集过滤器description>
<filter-name>encodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<description>字符集编码description>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<context-param>
<param-name>log4jConfigLocationparam-name>
<param-value>classpath:log4j.propertiesparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListenerlistener-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 ">
<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">
<context:component-scan base-package="webdemo.*"
use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
<context:include-filter type="annotation"
expression="org.springframework.web.bind.annotation.ControllerAdvice" />
context:component-scan>
<mvc:annotation-driven />
<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>.jspvalue>
property>
bean>
<bean id="stringConverter"
class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8value>
list>
property>
bean>
<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-8value>
<value>text/plain;charset=UTF-8value>
<value>application/json;charset=UTF-8value>
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 ListgetUserlist(){ System.out.println("get userlist"); List list = new ArrayList (); 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报文的组装,错误控制,日志切面等等,后续会进一步在这个基础上扩展。
个人GitHub地址: https://github.com/GrayWind33