一、接口设计
我们将会在系统中实现两个接口:
GET http://localhost:8888/hello
GET http://localhost:8888/hello/way
其中,第一个接口“/hello”将会返回“Hello World!” 的字符串;而第二个接口“/hello/way”则会返回一个包含用户信息的JSON字符串。
二、项目配置
我们需要在应用中添加如下依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
其中,
spring-webmvc是为了使用 Spring MVC 的功能
tomcat-embed-core是为了提供内嵌的 Servlet 容器,这样我们就无需依赖外部的容器,可以直接运行我们的应用。
jackson-core 和 jackson-databind为我们的应用提供 JSON 序列化的功能。
三、后台编码实现
领域模型
创建一个 User 类,代表用户信息。
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class User {
private String username;
private Integer age;
}
控制器
创建 HelloController 用于处理用户的请求。
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "Hello World!";
}
@RequestMapping("/hello/way")
public User helloWay() {
return new User("luopeng", 30);
}
}
其中,映射到“/hello”的方法将会返回“Hello World!” 的字符串;而映射到“/hello/way”则会返回一个包含用户信息的JSON字符串
应用配置
在本应用中,我们采用基于 Java 注解的配置。
AppConfiguration 是我们的主应用配置:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@ComponentScan(basePackages = { "com.epom" })
@Import({ MvcConfiguration.class })
public class AppConfiguration {
}
AppConfiguration 会扫描“com.epom”包下的文件,并自动将相关的 bean 进行注册。
AppConfiguration 同时又引入了 MVC 的配置类 MvcConfiguration:
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter());
}
}
@EnableWebMvc在springboot mvc或者java config配置中,如果我们项配置mvc相关的一些配置,那么就会涉及到这三个注解中的某个,那么他们之间有什么关系呢。@EnableWebMvc = WebMvcConfigurationSupport,使用@EnableWebMvc注解就等于扩展了WebMvcConfigurationSupport,但是没有扩展任何方法。具体用法有如下三种:
@EnableWebMvc+extends WebMvcConfigurationAdapter,在扩展的类中重写父类的方法即可,这种方式会屏蔽springboot的@EnableAutoConfiguration中的设置。
extends WebMvcConfigurationSupport,在扩展的类中重写父类的方法即可,这种方式会屏蔽springboot的@EnableAutoConfiguration中的设置。
extends WebMvcConfigurationAdapter,在扩展的类中重写父类的方法即可,这种方式依旧使用springboot的@EnableAutoConfiguration中的设置。
MvcConfiguration 配置类一方面启用了 MVC 的功能,另一方面添加了 Jackson JSON 的转换器。
最后,我们需要引入 tomcat 服务器 tomcatServer:
import java.io.File;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Service;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.core.StandardWrapper;
import org.apache.catalina.startup.ContextConfig;
import org.apache.catalina.startup.Tomcat;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import com.epom.web.AppConfiguration;
public class TomcatServer {
public static void main(String[] args) throws LifecycleException {
String workspace = System.getProperty("user.dir");
String webapp = new File(workspace,"src/main/webapp").getPath();
Tomcat tomcat = new Tomcat();
// 看源码发现,他只能设置一个service,直接拿默认的
Service service = tomcat.getService();
// 创建连接器,并且添加对应的连接器,同时连接器指定端口
Connector connector = new Connector();
connector.setPort(8888);
service.addConnector(connector);
// 创建一个引擎,放入service中
Engine engine = new StandardEngine();
service.setContainer(engine);
engine.setDefaultHost("localhost");
engine.setName("myTomcat");
// 添加host
Host host = new StandardHost();
engine.addChild(host);
host.setName("localhost");
// 在对应的host下面创建一个 context 并制定他的工作路径,会加载该目录下的所有class文件,或者静态文件
tomcat.getHost().setAppBase("webapp");
StandardContext context = (StandardContext) tomcat.addContext(host, "/", webapp);
// 初始化ContextConfig配置
context.addLifecycleListener(new ContextConfig());
WebApplicationContext webApplicationContext = webApplicationContext();
// 创建一个servlet
Wrapper myservlet = new StandardWrapper();
myservlet.setServlet(new DispatcherServlet(webApplicationContext));
myservlet.setName("srpingmvc");
// 把servlet加入到contxt中
context.addChild(myservlet);
// 这里注意,要先添加到contxt中在映射路径,不然会空指针
myservlet.addMapping("/");
context.addApplicationEventListener(new ContextLoaderListener(webApplicationContext));
//tomcat启动
tomcat.start();
//保持主线程不退出
tomcat.getServer().await();
}
private static WebApplicationContext webApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfiguration.class);
return context;
}
}
四、运行
十二月 18, 2019 11:11:00 上午 org.apache.catalina.core.StandardContext setPath
警告: A context path must either be an empty string or start with a '/' and do not end with a '/'. The path [/] does not meet these criteria and has been changed to []
十二月 18, 2019 11:11:00 上午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["http-nio-8888"]
十二月 18, 2019 11:11:00 上午 org.apache.catalina.core.StandardService startInternal
信息: Starting service [Tomcat]
十二月 18, 2019 11:11:00 上午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet engine: [Apache Tomcat/9.0.27]
十二月 18, 2019 11:11:00 上午 org.apache.catalina.startup.ContextConfig getDefaultWebXmlFragment
信息: No global web.xml found
十二月 18, 2019 11:11:01 上午 org.apache.catalina.core.ApplicationContext log
信息: No Spring WebApplicationInitializer types detected on classpath
十二月 18, 2019 11:11:01 上午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["http-nio-8888"]十二月 18, 2019 11:11:00 上午 org.apache.catalina.core.StandardContext setPath
警告: A context path must either be an empty string or start with a '/' and do not end with a '/'. The path [/] does not meet these criteria and has been changed to []
十二月 18, 2019 11:11:00 上午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["http-nio-8888"]
十二月 18, 2019 11:11:00 上午 org.apache.catalina.core.StandardService startInternal
信息: Starting service [Tomcat]
十二月 18, 2019 11:11:00 上午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet engine: [Apache Tomcat/9.0.27]
十二月 18, 2019 11:11:00 上午 org.apache.catalina.startup.ContextConfig getDefaultWebXmlFragment
信息: No global web.xml found
十二月 18, 2019 11:11:01 上午 org.apache.catalina.core.ApplicationContext log
信息: No Spring WebApplicationInitializer types detected on classpath
十二月 18, 2019 11:11:01 上午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["http-nio-8888"]十二月 18, 2019 11:11:00 上午 org.apache.catalina.core.StandardContext setPath
警告: A context path must either be an empty string or start with a '/' and do not end with a '/'. The path [/] does not meet these criteria and has been changed to []
十二月 18, 2019 11:11:00 上午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["http-nio-8888"]
十二月 18, 2019 11:11:00 上午 org.apache.catalina.core.StandardService startInternal
信息: Starting service [Tomcat]
十二月 18, 2019 11:11:00 上午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet engine: [Apache Tomcat/9.0.27]
十二月 18, 2019 11:11:00 上午 org.apache.catalina.startup.ContextConfig getDefaultWebXmlFragment
信息: No global web.xml found
十二月 18, 2019 11:11:01 上午 org.apache.catalina.core.ApplicationContext log
信息: No Spring WebApplicationInitializer types detected on classpath
十二月 18, 2019 11:11:01 上午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["http-nio-8888"]
分别在浏览器中访问 http://localhost:8888/hello 和 http://localhost:8888/hello/way 地址进行测试, 能看到图1和图2的响应效果。