spring boot(学习笔记第六课)
- 配置类与XML配置,注册拦截器和启动任务
学习内容:
- 配置类和XML配置
- 注册拦截器
- 启动系统任务
- 整合Servlet,Filter和Listener
- 路径映射
1. 配置类和XML配置
- 配置类和XML配置
spring boot
提倡使用java
代码进行配置,但是同样可以通过xml
文件进行配置。 - 首先定义一个
bean class
。public class HelloBean { public String sayHello(String name){ return "hello," + name; } }
- 定义一个
xml
文件来进行beans
的定义。<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.example.demo.beans.HelloBean" id="hello"/> </beans>
- 定义
java class
对xml
文件进行加载。@Configuration @ImportResource("classpath:/beans_config/beans.xml") public class HelloBeanConfig { }
- 在
controller
中使用bean
。public class HelloController { @Autowired private HelloBean hello; @Autowired private ShopConfig shopConfig; @GetMapping("/hello") @ResponseBody public String hello(){ String shop = "name " + shopConfig.getName() + "owner" + shopConfig.getOwner() + "location" + shopConfig.getLocation(); return hello.sayHello(shop); }
- 再次访问
controller
,看到bean
已经正常动作。
2. 注册拦截器
spring boot
提供AOP风格的拦截器,对请求request
和应答response
以及ModelAndView
进行调整。
- 开始定义
HandleInterpretor
public class CustomHandleInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler){ System.out.println("Costom handle interceptor >>> preHandle"); return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, ModelAndView mv) { System.out.println("Costom handle interceptor >>> postHandle"); } }
- 使用
@Configuration
注解定义WebMvcConfig
这里拦截大多数的public class WebMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry interceptorRegistry) { interceptorRegistry.addInterceptor(new CustomHandleInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/hello"); } }
pattern
,除非hello
。 - 测试拦截器
interceptor
@GetMapping("/book") @ResponseBody public Book book() { Book book = new Book(); book.setAuthor("finlay"); book.setName("spring boot"); book.setPrice(14.5F); book.setPublicatationDate(new Date()); return book; }
注意,这时候访问/hello
,能够看出是不经过自定义的interceptor
的。
3. 启动系统任务
CommandLineRunner
顾名思义,这个@Component就是使用命令行执行一样,在spring boot
的应用程序启动的时候作为命令行来启动执行。
- 定义
CommandLineRunner
的@Component
@component
定义了之后,spring boot
能够将该CommandLineRunner
扫描加载。
@Order
决定了复数个CommandLineRunner
的执行顺序,数字越小越先执行。@Component @Order(1) public class StartCommandLineRunner implements CommandLineRunner { @Override public void run(String... args)throws Exception{ for(String arg : args) { System.out.println(arg); } System.out.println("number of args is " + args.length); } }
- 使用
maven
的package
功能打包,这里方便我们在命令行java -jar
的形式的测试。
- 启动
spring boot
应用程序,测试结果。
java -jar demo-0.0.1-SNAPSHOT.jar finlay 20240612
ApplicationRunner
和CommandLineRunner
几乎一样,传递参数的形式不同。不再赘述。
可以在一些spring boot
应用启动时候的做的工作,放到这里执行。
4. 整合Servlet,Filter和Listener
通过controller
组件,可以进行大多数的场景的对应,但是对于一些web组件的整合,传统的Servlet
,Filter
和Listener
进行对应。
- 使用
WebServlet
- 定义
WebServlet
public class CustomServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException { doPost(httpServletRequest, httpServletResponse); } @Override protected void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException { System.out.println("name>>> " + httpServletRequest.getParameter("name")); } }
- 对于
spring boot
的main class
,使用@ServletComponentScan
@SpringBootApplication @ServletComponentScan public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
- 测试WebServlet`
注意,/book这个URL虽然已经在controller里面已经定义,但是这里WebServlet已经完全取代了controller来处理/book。
- 使用
WebFilter
可以选择继续向下处理,还是WebFilter
截断处理。
- 定义
WebFillter
-
向下传递
WebServlet
注意,doFilter方法里面,调用chain.doFilter(request,response);@WebFilter("/*") public class CustomWebFilter implements Filter { @Override public void init(FilterConfig filterConfig) { System.out.println("CustomWebFilter >>> init"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("CustomWebFilter >>> doFilter"); chain.doFilter(request,response); } @Override public void destroy() { System.out.println("CustomWebFilter >>> destroy"); Filter.super.destroy(); } }
测试执行效果,前面的定义的
WebServlet
会被继续执行。
-
不向下传递
WebServlet
注意,doFilter方法里面,不调用chain.doFilter(request,response);@WebFilter("/*") public class CustomWebFilter implements Filter { @Override public void init(FilterConfig filterConfig) { System.out.println("CustomWebFilter >>> init"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("CustomWebFilter >>> doFilter"); // chain.doFilter(request,response); } @Override public void destroy() { System.out.println("CustomWebFilter >>> destroy"); Filter.super.destroy(); } }
执行测试结果,可以看出没有执行
WebServlet
。
-
- 使用
ServletRequestListener
执行之后,任意的@WebListener public class CustomWebListener implements ServletRequestListener { @Override public void requestDestroyed(ServletRequestEvent servletRequestEvent){ System.out.println("CustomWebListener >>> requestDestroyed"); } @Override public void requestInitialized(ServletRequestEvent servletRequestEvent){ System.out.println("CustomWebListener >>> requestInitialized"); } }
Servlet
都会被监听到,执行相应的requestDestroyed
和requestInitialized
。
5. 路径映射
目前如果定义了thymeleaf
模板视图view
,之后定义相应的controller
,可以返回相应的view
来达到画面渲染的目的,但是如果就是静态页面,不是采用模板的方式,那么可以直接使用快捷方式直接表示view
,从性能上会有一些提高。
注意这里只能使用模板,不能使用静态资源。/resources/static/是不行的。
- 定义
@Configuration
的WebMvcConfigurer
接口的实现类。@Configuration public class WebDirectMapping implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry viewControllerRegistry) { viewControllerRegistry .addViewController("/login") .setViewName("login"); viewControllerRegistry .addViewController("/index") .setViewName("index"); } }
- 定义
/resources/templates/index.html
和/resource/templates/login.html
两个模板页面。
- 页面代码简单示例一下。
login
和index
可以通过title
简单区分。<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>INDEX</title> <script src="jquery.js"></script> </head> <body> <div id="contentDiv"></div> <div id="deleteResult"></div> <input type="button" value="提交数据" onclick="getData()"><br> <input type="button" value="删除数据" onclick="deleteData()"><br> </body> </html>
- 之后访问下面的
url
,可以进行测试。- https://localhost:8080/login
- https://localhost:8080/