@Controller与原生Servlet都可以响应http的url请求,那么他们之间有什么区别呢?如果匹配的url相同,会不会冲突呢?谁的优先级更高呢?带着这些问题,我们且来分析一下。
下面我们来编写@Controller与原生Servlet的代码,其中Servlet由@ServletComponentScan配合@WebServlet实现,重写HttpServlet类的doGet方法即可。具体实现如下所示:
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
@ServletComponentScan
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接口
@WebServlet(urlPatterns = "/test/hello")
public class AnnotationServlet extends HttpServlet {
@Override
protected void doGet(HttpServlet Requestreq, HttpServlet Response 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();
}
}
}
}
接着我们来测试一下,如下图所示,访问/test/hello路径返回的是原生Servlet中的结果。
通过测试,我们可以发现,controller接口没有被访问到。那么,controller接口到底有没有注册到springboot容器中了?打印log看看便知:
logging:
level:
org.springframework.web: trace
通过log可以看出,controller接口是成功注册到springboot容器中的。这说明两者并不会产生冲突报错,并且原生Servlet的优先级高于@Controller。
具体地,一个请求的调用链路如下图所示: