一、前言
在实际开发中,有时候我们可能使用springboot注册web组件,实现某些功能,比如我们需要生成一些api来提供对外的服务,而对应的路径其实是不固定的,那么这种情况下,其实是可以通过这种方式来注册web组件的。
二、如何实现?
1.使用SpringBoot注解加继承HttpServet类实现注册Servlet组件。
@WebServlet("/api")
public class APIServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
log.debug("servlet execute");
String servletPath = request.getRequestURI();
servletPath = servletPath.substring(apiContext.length() + 2);
PrintWriter out = null;
try {
out = response.getWriter();
ResponseDto responseDto = process(servletPath, request, response);
out.append(JSON.toJSONString(responseDto));
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
out.append(JSON.toJSONString(ResponseDto.fail(e.toString())));
log.error(e.toString(), e);
} finally {
if (out != null)
out.close();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
public ResponseDto process(String path, HttpServletRequest request, HttpServletResponse response) {
System.out.println("请求处理");
ResponseDto dto = new ResponseDto();
return dto;
}
}
2.通过继承HttpServet类加配置类来进行注册。
public class APIServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
log.debug("servlet execute");
String servletPath = request.getRequestURI();
servletPath = servletPath.substring(apiContext.length() + 2);
PrintWriter out = null;
try {
out = response.getWriter();
ResponseDto responseDto = process(servletPath, request, response);
out.append(JSON.toJSONString(responseDto));
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
out.append(JSON.toJSONString(ResponseDto.fail(e.toString())));
log.error(e.toString(), e);
} finally {
if (out != null)
out.close();
}
}
}
新建一个配置类,将该Servlet加载到Spring容器中,配置类代码如下:
@Slf4j
@Configuration
public class ServletConfig {
@Value("${dbapi.api.context}")
String apiContext;
@Autowired
private APIServlet apiServlet;
@Bean
public ServletRegistrationBean getServletRegistrationBean() {
String format = String.format("/%s/*", apiContext);
ServletRegistrationBean bean = new ServletRegistrationBean(apiServlet);
bean.addUrlMappings(format);
log.info("regist APIServlet servelet for {} urlMappings",format);
return bean;
}
}
两种注册方式都是可用的。
3.注册Filter组件实现过滤。
@Slf4j
@Component
@WebFilter("/api")
public class ApiIPFilter implements Filter {
@Autowired
private IPService ipService;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException {
log.debug("IP filter execute");
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String originIp = IPUtil.getOriginIp(request);
String method = request.getMethod();
PrintWriter out = null;
try {
//js跨域的预检请求,不经过处理逻辑。开发模式下,前端启动,访问8521的页面进行请求测试会跨域
if (method.equals("OPTIONS")) {
response.setStatus(HttpServletResponse.SC_OK);
return;
}
boolean checkIP = ipService.checkIP(originIp);
if (!checkIP) {
out = response.getWriter();
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
out.append(JSON.toJSONString(ResponseDto.fail("Illegal ip (" + originIp + "), access forbidden")));
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
out.append(JSON.toJSONString(ResponseDto.fail(e.toString())));
log.error(e.toString());
} finally {
if (out != null) {
out.close();
}
}
}
这里会对某些IP进行过滤。
最后启动类中的@ServletComponentScan注解扫描web组件。
@SpringBootApplication
//SpringBoot启动时扫描注册注解标注的Web组件
@ServletComponentScan
public class SpringbootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class, args);
}
}