SpringBoot +CXF 发布WebService服务后其他http请求不能使用

一、概述

   因为项目需要,需要再原先项目中发布或者调用WebService服务,考虑到集成Springboot框架,于是采用CXF框架。
   WebService注册服务如下:

 1 @Configuration
 2 public class CxfWebServiceConfig {
 3 
 4 
 5     @Autowired
 6     private HelloWebService helloWebService;
 7 
 8     @Bean
 9     public ServletRegistrationBean dispatcherServlet() {
10         return new ServletRegistrationBean(new CXFServlet(), "/service/*");//发布服务名称
11     }
12 
13     @Bean(name = Bus.DEFAULT_BUS_ID)
14     public SpringBus springBus() {
15         return new SpringBus();
16     }
17 
18     public HelloWebService helloWebService(){
19         return new HelloWebServiceImpl();
20     }
21 
22     @Bean
23     public Endpoint endpoint(){
24         EndpointImpl endpoint = new EndpointImpl(springBus(),helloWebService);
25         endpoint.publish("/HelloWebService");
26         return endpoint;
27     }
28 
29 }

在将CXF集成之后,WebService服务能够正常访问,但是原先的http服务不能访问
   因为springboot程序中默认注册的是 dispatcherServlet,在发不了WebService服务之后,相当于手动配置 ServletRegistrationBean,这时springboot不会再去注册默认的dispatcherServlet,解决办法就是需要我们在启动类里手动去注册一个dispatcherServlet

spring boot中注册Servlet的两种方式

但spring boot把tomcat都给隐藏了,更别说web.xml了。好在提供了另外的方式配置servlet。
1.@WebServlet注解:
这个是javaee的注解,是servlet3.0以后提供的。spring boot会扫描这个注解,并将这个注解注解的类注册到web容器中作为一个servlet。
但是DispatcherServlet并不是自定义的servlet,而是框架提供的servlet,所以此方法不行。
2.ServletRegistrationBean:
这个bean是由spring boot提供专门来注册servlet的,可以象注册bean一样去配置servlet。

 1     @Bean
 2     public ServletRegistrationBean dispatcherServlet() {
 3         //注解扫描上下文
 4         AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
 5         //项目包名
 6         applicationContext.scan("com.surfilter.*");
 7         DispatcherServlet rest_dispatcherServlet = new DispatcherServlet(applicationContext);
 8         ServletRegistrationBean registrationBean = new ServletRegistrationBean(rest_dispatcherServlet);
 9         registrationBean.setLoadOnStartup(1);
10         registrationBean.addUrlMappings("/*");
11         //一定要加上此行
12         registrationBean.setName("rest_dispatcherServlet");
13         return registrationBean;
14     }        
其中需要注意的是registration.setName("rest_dispatcherServlet"),这个语句很重要,因为name相同的ServletRegistrationBean只有一个会生效,也就是说,后注册的会覆盖掉name相同的ServletRegistrationBean。
如果不指定,默认为“dispatcherServlet”而spring boot提供的DispatcherServlet的name就是“dispatcherServlet”。可以在spring boot的DispatcherServletAutoConfiguration类中找到:
 1 public ServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet) {
 2             ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet, new String[]{this.serverProperties.getServletMapping()});
 3             registration.setName("dispatcherServlet");
 4             registration.setLoadOnStartup(this.webMvcProperties.getServlet().getLoadOnStartup());
 5             if(this.multipartConfig != null) {
 6                 registration.setMultipartConfig(this.multipartConfig);
 7             }
 8 
 9             return registration;
10         }
11     }

所以为了不覆盖默认的dispatcherServlet,必须指定一个别的名称

同时,在自定义的DispathcerServlet绑定的配置类上,要配置报扫描的话,必须要加上@EnableWebMvc注解,不然不会扫描@Contrller注解。

1 @RestController
2 @RequestMapping("/api/1.0/hello")
3 @EnableWebMvc
4 public class RestController {
5     ......
6 }

屏蔽rest服务DispatcherServlet对静态资源的访问

最后还有一个小问题,因为想让额外配置的一个DispatcherServlet专门用于提供rest服务,但是这样配置之后,访问localhost/rest/时会访问到页面等静态资源,感觉怪怪的。
因为spring boot默认是对静态资源做了映射的,但如果不想要访问到任何静态的资源,可以修改这个映射。
两种方式:
1.在application.yml中配置:

1 spring:
2   mvc:
3     #默认为/**
4     static-path-pattern: /**
5   resources:
6     #默认为classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ 。配置多个路径,中间用逗号隔开。
7     static-locations: 
如果在这里配置,就会影响整个springboot项目。但默认的DispatcherServlet是需要访问静态资源的,所以不能在这里配置。
2.继承WebMvcConfigurerAdapter的java类中配置:
1 @Configuration
2 @EnableWebMvc
3 public class Cfg_View extends WebMvcConfigurerAdapter{
4     @Override
5     public void addResourceHandlers(ResourceHandlerRegistry registry) {
6         registry.addResourceHandler("/**");
7     }
8 }
重写addResourceHandlers方法,只指定resourceHandler,不指定resourceLocation,这样写就能够使其拦截掉所有对静态资源的访问,并且不会返回任何静态资源。这里的配置是可指定的,只需要让负责rest服务的DispatcherServlet的上下文扫描这个配置类就可以了。不会影响默认的DispatcherServlet
原文地址:https://www.cnblogs.com/lgjava/p/12462192.html