初学SpringBoot一【访问Controller、整合Servlet、整合Filter、整合Listener】
前言
现如今效率成为了企业竞争的头等大事,而作为诸多行业中迭代率最高的软件行业来说,快速完成项目开发也成为了很多架构师首个思考的目标。而SpringBoot作为快速搭建项目的平台现在已经成为了项目开发的基本框架
下面就让我们一起来学习SpringBoot的基本使用以及原理
一、SpirngBoot介绍
SpringBoot是Spring的一个子项目,能够帮助开发者快速搭建企业级项目环境
二、基本使用
1.快速搭建环境
1.1.1 使用SpringBoot搭建一个HelloWord项目
- 第一步:导入Maven依赖
SpringBoot地址:https://docs.spring.io/spring-boot
使用maven导入SpringBoot相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<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.springboot</groupId>
<artifactId>SpringBootDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 第一步:添加spring-boot-starter-parent 这是作为SpringBoot的基础依赖包 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
</parent>
<!-- 第一步:添加spring-boot-starter-web 这是依赖包提供了maven的默认配置,方便开发者管理依赖 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
注意: 新建SpringBoot项目必须继承spring-boot-starter-parent 这个是SpringBoot项目的基础依赖包
- 第二步:创建一个maven子项目
工程搭建好后的结构图如下:
- 第三步:创建一个Controller
/**
- 这里和创建普通的Controller一样
- @RestController 这个注解和 @Controller注解作用一样,具体的区别后面会详细讲解
- @EnableAutoConfiguration 这个注解的作用是为了让@SpringBootApplication 类扫描到,具体后面会详细讲解
*/
@RestController
public class HelloWordController {
@RequestMapping("hello")
@ResponseBody
public Map<String,Object> m1(){
Map<String,Object> result = new HashMap<>();
result.put("hello!!!","SpringBoot");
return result;
}
}
有了Controller类后,还需要SpringBoot的启动类来加载这个Controller
- 第三步:创建一个SpringBoot启动器
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* SpringBoot的启动类需要用@SpringBootApplication来标识
*/
@SpringBootApplication
public class ControllerApplication {
public static void main(String[] args) {
SpringApplication.run(ControllerApplication .class,args);
}
}
- 第四步:启动并访问该Controller
启动的方式非常简单,在启动类中右键选择run执行该启动类就可以了
如图:
这样就启动完成啦!!!
接下来就可以在浏览器直接访问了
总结
提示:这里在创建SpringBoot的启动类的时候要注意一个问题;启动类必须是Controller的上级或者同一个包下,否则SpringBoot启动类无法扫描到Controller
这是一个简单的SpringBoot样例。后面的文章我会继续对SpringBoot的各个细节挨个详细介绍,由浅至深,力求每个SpringBoot感兴趣的朋友都能彻底了解SpringBoot
1.1.2 SpringBoot整合Servlet
看到这里可能有许多小伙伴产生疑问,SpringBoot中已经为我们提供了web的那个一套东西,为什么还要再次整合Servlet呢,这岂不是在画蛇添足吗?其实并非多此一举,在项目中难免会遇到集成第三方接口的问题,这时候我们却发现SpringBoot中没有web.xml文件,那怎么办呢?SpringBoot已经提供了WEB三大组件的整合方式。让我们一起来看看吧。
方式一:注解扫描配置
- List item第一步:创建Servlet类
package com.test.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 在整合Servlet之前我们先回忆一下之前配置Servlet的方式
* 之前是在web.xml中配置servlet的,如下
* <servlet>
* <servlet-name>SpringBootServletTest</servlet-name>
* <servlet-class>com.test.servlet.SpringBootServletTest</servlet-class>
* </servlet>
* <servlet-mapping>
* <servlet-name>SpringBootServletTest</servlet-name>
* <url-pattern>/first</url-pattern>
* </servlet-mapping>
* 可以看出来,之前这种配置节点的方式很是麻烦,整个项目下来web.xml文件中的节点非常的臃肿庞大
* 现在只需要一个@WebServlet注解直接搞定
*/
@WebServlet(name = "SpringBootServletTest",urlPatterns = "/first")
public class SpringBootServletTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("请求进入了Servlet中的doGet方法。。。。。。。");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
可以看出来,之前这种配置节点的方式很是麻烦,整个项目下来web.xml文件中的节点非常的臃肿庞大。
现在只需要一个@WebServlet注解直接搞定
@WebServlet注解讲解
@WebServlet注解是一个类级别的注解。主要作用是用来标识该类是一个Servlet。
容器在加载时会根据该注解的具体的属性配置将该类部署成一个Servlet类。
其中主要的属性参数如下
- 第二步:创建SpringBoot启动类
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
* SpringBoot启动类,写法老规矩重点讲一下@ServletComponentScan这个注解
* @ServletComponentScan
* 这个注解的作用是会自动扫描启动器类所在的包以及子包中所有的WEB注解
* 例如:@WebServlet、@WebFilter、@WebListener
*/
@SpringBootApplication
@ServletComponentScan
public class ServletApplication {
public static void main(String[] args) {
SpringApplication.run(ServletApplication.class,args);
}
}
- 第三步:启动并访问
在浏览器中输入http://127.0.0.1:8080/first地址访问后
控制台打印出来Servlet类中doGet中的输出语句,表示成功啦!!!
方式二:组件注册
- 第一步:创建一个普通的Servlet类
创建一个普通的Servlet类,不需要注解
package com.test.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 创建一个普通的Servlet类,不需要注解
*/
public class SpringBootServletTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("请求进入到了Servlet类中的doGet方法中。。。。。。。。");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
- 第二步:编写SpringBoot启动类
package com.test;
import com.test.servlet.SpringBootServletTest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
/**
* 可以看到这里没有扫描包注解了,因为我们不使用注解的方式,所以不再使用扫描包注解了
*/
@SpringBootApplication
public class ServletApplication {
public static void main(String[] args) {
SpringApplication.run(ServletApplication.class,args);
}
/**
* 在启动类中指定一个方法,返回值必须是ServletRegistrationBean,方法名称随便写
* @return ServletRegistrationBean
* @Bean 这里看到这个注解后很是好奇,为啥不是写在类上的。
* 于是在网上查资料后才知道,这玩意是告诉spring这个方法的返回值是一个对象,并且需要自动装配
*/
@Bean
public ServletRegistrationBean getBean(){
/**
* 创建一个Servlet构造器,并且指定需要构造的Servlet对象
*/
ServletRegistrationBean bean = new ServletRegistrationBean(new SpringBootServletTest());
/**
* bean.setName("springBootServletTest");
* 在不指定servlet名称的情况下,servlet默认使用类名首字母小写作为servlet的name值
*/
//bean.setName("springBootServletTest");
bean.addUrlMappings("/first");
return bean;
}
}
@Bean注解与@Component注解的区别
相同点:两者的结果都是为spring容器注册Bean。
不同点:
@Component 通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中,是一个类级别的注解。@Component注解表明一个类会作为组件类,并告知Spring要为这个类创建bean。
@Bean注解表示告诉Spring这个方法最终会返回一个对象,并且要注册为Spring的上下文中的bean,通常这个方法中的逻辑最终会返回一个实例。
- 第三步:启动并访问
结果如下
1.1.3 SpringBoot整合Filter
方式一:注解扫描配置
- List item第一步:创建Filter类
package com.test.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(filterName = "SpringBootFilterTest",urlPatterns = "/myFilter")
public class SpringBootFilterTest implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("请求进入filter。。。。");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("请求离开filter。。。。");
}
@Override
public void destroy() {
}
}
- 编写启动类
SpringBoot启动类还是一样,这里注意一下,如果用注解的方式,上面已经写过启动类了,无需再写。
运行结果如下
方式二:组件注册
- 第一步:创建一个普通的Filter类
创建一个普通的Filter类,不需要注解
package com.test.filter;
import javax.servlet.*;
import java.io.IOException;
public class SpringBootFilterTest implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("请求进入filter。。。。");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("请求离开filter。。。。");
}
@Override
public void destroy() {
}
}
- 第二步:编写SpringBoot启动类
package com.test;
import com.test.filter.SpringBootFilterTest;
import com.test.servlet.SpringBootServletTest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
/**
* 可以看到这里没有扫描包注解了,因为我们不使用注解的方式,所以不再使用扫描包注解了
*/
@SpringBootApplication
public class ServletApplication {
public static void main(String[] args) {
SpringApplication.run(ServletApplication.class,args);
}
/**
* 在启动类中指定一个方法,返回值必须是ServletRegistrationBean,方法名称随便写
* @return ServletRegistrationBean
* @Bean 这里看到这个注解后很是好奇,为啥不是写在类上的。
* 于是在网上查资料后才知道,这玩意是告诉spring这个方法的返回值是一个对象,并且需要自动装配
*/
@Bean
public ServletRegistrationBean getBean(){
/**
* 创建一个Servlet构造器,并且指定需要构造的Servlet对象
*/
ServletRegistrationBean bean = new ServletRegistrationBean(new SpringBootServletTest());
/**
* bean.setName("springBootServletTest");
* 在不指定servlet名称的情况下,servlet默认使用类名首字母小写作为servlet的name值
*/
//bean.setName("springBootServletTest");
bean.addUrlMappings("/first");
return bean;
}
@Bean
public FilterRegistrationBean getFilterBean(){
/**
* 创建一个filter构造器,并且指定需要构造的filter对象
*/
FilterRegistrationBean<SpringBootFilterTest> bean = new FilterRegistrationBean(new SpringBootFilterTest());
/**
* bean.setName("springBootFilterTest");
* 在不指定filter名称的情况下,servlet默认使用类名首字母小写作为filter的name值
*/
//bean.setName("springBootFilterTest");
bean.addUrlPatterns("/myFilter");
return bean;
}
}
访问http://127.0.0.1:8080/myFilter
运行结果如下:
小提示: 这里有个提示说一下,在方法中注册组件时,如果不指定name值,默认使用类名首字母小写来作为bean的唯一标识
1.1.4 SpringBoot整合Listener
方式一:注解扫描配置
- List item第一步:创建Listener类
package com.test.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* 老规矩,鲁迅先生说过:不经常复习知识的程序员不是好程序员!!!
* 之前我们在web.xml中配置监听器时的写法如下
*<listener>
* <listener-class>com.test.listener.SpringBootListener</listener-class>
*</listener>
* 在SpringBoot使用注解的方式
*/
@WebListener
public class SpringBootListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("进入监听器Spring开始初始化。。。。。。");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
- 编写启动类
SpringBoot启动类还是一样,这里注意一下,如果用注解的方式,上面已经写过启动类了,无需再写。
运行结果如下
方式二:组件注册
- 第一步:创建一个普通的Listener类
创建一个普通的Listener类,不需要注解
package com.test.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class SpringBootListenerTest implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("进入监听器,Spring开始初始化。。。。。");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
- 第二步:编写SpringBoot启动类
在上面的Filter的启动类中加入下面的方法就可以了
@Bean
public ServletListenerRegistrationBean getListenerBean(){
/**
* 创建一个Listener构造器,并且指定需要构造的Listener对象
*/
ServletListenerRegistrationBean<SpringBootListenerTest> bean = new ServletListenerRegistrationBean<>(new SpringBootListenerTest());
return bean;
}
启动项目结果如下:
拓展 @Configuration的用法
提示:上面组件注册的方式其实还有一种写法,感兴趣的小伙伴可以看一下
我就拿Servlet来举个栗子吧
直接上代码
package test.configuration;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import test.servlet.SpringBootServletTest;
@Configuration
public class ServletConfig {
@Bean
public ServletRegistrationBean<SpringBootServletTest> getSpringBootServletTestBean(){
ServletRegistrationBean<SpringBootServletTest> bean = new ServletRegistrationBean<>();
bean.setServlet(new SpringBootServletTest());
bean.addUrlMappings("/first");
return bean;
}
}
package test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ServletApplication {
public static void main(String[] args) {
SpringApplication.run(ServletApplication.class,args);
}
}
系不系这样的bean更方便管理了,而且启动类中也变得干净整洁了。系不系呀!嘘··嘘…嘘嘘,系不系,说呀,系不系。唉,这就对了。他说他已经回到了过去,还说让紫霞仙子能够早日找到一位如意郎君呢。哼哼~。哈哈,哭了。。。。