接着上一篇的controller接口被springsecurity配置覆盖的问题,我想到了另外一个新问题
就是,springboot的controller接口和servlet原生接口,如果路径重复了,会发生什么情况?
猜想:
1、项目无法启动,报错访问路径重复。
2、项目正常启动,有效的是controller接口。
3、项目正常启动,有效的是servlet接口。
为了这个问题,我专门写了个测试工程,测试了一下。
首先,要会springboot如何开发servlet原生接口。
两种实现方式:
1、@ServletComponentScan+@WebServlet(urlPatterns = “/testServlet/*”)
2、@Bean+ServletRegistrationBean
参考:https://blog.csdn.net/weixin_34101784/article/details/91981917
我的例子如下:
import com.pzj.hello.servlet.Test2Servlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
//controller接口
@GetMapping("/test/hello")
public String hello(){
return "hello!";
}
//关键是这里,给web注册一个servlet接口
@Bean
public ServletRegistrationBean MyServlet1(){
//保持servlet接口的访问路径和controller接口的访问路径相同
return new ServletRegistrationBean(new Test2Servlet(),"/test/hello");
}
}
原生servlet类,其实和以前学习web开发的servlet写法一样
只是,以前通过web.xml注册一个servlet接口
现在通过@Bean+ServletRegistrationBean注册一个servlet接口
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class Test2Servlet extends HttpServlet {
private static final long serialVersionUID = -5327348304390633663L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/json; charset=utf-8");
String jsonStr = "{\"name\":\"fly\",\"type\":\"虫子1\"}";
PrintWriter out = null;
try {
out = resp.getWriter();
out.write(jsonStr);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
}
}
完成以上代码的编写之后,一个servlet接口和controller接口就开发好了
接下来进行测试
访问接口:http://127.0.0.1:8080/test/hello
通过测试,我们可以发现,controller接口没有被访问到
那么,controller接口到底有没有注册到springboot容器中了?
打印log看看便知:
logging:
level:
org.springframework.web: trace
通过log可以看出,controller接口是成功注册到springboot容器中的
结论:在访问接口的时候,如果servlet接口路径和controller接口路径相同,则请求优先被servlet接口拦截并处理调,无法访问到controller接口,但是,路径相同,不影响项目正常启动和运行。
servlet接口重名也不影响项目正常运行,@Bean+ServletRegistrationBean这个方式的优先级高于@ServletComponentScan+@WebServlet(urlPatterns = “/testServlet/*”)高于controller接口,并且servlet接口谁先被加载,则谁生效
进一步推理,两者的关系应该如下图:
那么,servlet到底由谁来管理了?Tomcat(Tomcat又叫servlet容器)?有待进一步验证!
参考:
https://blog.csdn.net/weixin_39794130/article/details/114205810
https://blog.csdn.net/weixin_35781693/article/details/114098789
对应的工程:D:/IDEAWorkspace/hello