spring boot兼容struts2、Http Servlet、web.xml

有些老项目还在使用原始的Http Servlet或是struts2, 而新功能都期望使用spring, 而spring已经不使用web.xml配置了. 折中的解决方法:

整合struts2

@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
    @Bean
    public FilterRegistrationBean registration() {
    	//web.xml中的struts filter移到代码中
        StrutsPrepareAndExecuteFilter filter = new StrutsPrepareAndExecuteFilter();
        FilterRegistrationBean<StrutsPrepareAndExecuteFilter> registration =
                new FilterRegistrationBean<>(filter);
        registration.addUrlPatterns("/test/*");
        registration.addInitParameter("config", "struts-default.xml,struts2/struts-test.xml");
        return registration;
    }
}

兼容原始的Servlet

public class MyServlet1 extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		resp.getWriter().write("hello servlet1");
	}
}

public class MyServlet2 extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		resp.getWriter().write("hello servlet2");
	}
}


@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
    
    @Bean
    public ServletRegistrationBean<HttpServlet> helloServlet1() {
        ServletRegistrationBean<HttpServlet> servRegBean = new ServletRegistrationBean<>();
        servRegBean.setServlet(new MyServlet1());
        servRegBean.addUrlMappings("/servlet1");
        return servRegBean;
    }

    @Bean
    public ServletRegistrationBean<HttpServlet> helloServlet2() {
        ServletRegistrationBean<HttpServlet> servRegBean = new ServletRegistrationBean<>();
        servRegBean.setServlet(new MyServlet2());
        servRegBean.addUrlMappings("/servlet2");
        return servRegBean;
    }
}

不推荐使用@ServletComponentScan@WebServlet, 因为不生效

自动批量导入web.xml中的Servlet

如果web.xml中配置的servlet太多, 手动改太累, 可以使用dom4j解析web.xml, 然后批量导入
先将web.xml移到resources目录下

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.http.HttpServlet;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;

@Configuration
public class WebxmlCompatible implements ServletContextInitializer {
    private final static Logger log = LogManager.getLogger(WebxmlCompatible.class);

    private static class ServletConfig{
        public String name; //servlet-name
        public String clsssName;
        public List<String> patterns = new LinkedList<>(); //url-pattern
        public boolean loadOnStartup; //load-on-startup
        public boolean asyncSupported;
        public HashMap<String, String> initParams = new HashMap<>();
        public MultipartConfigElement multipart = null;
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        try (InputStream inputStream = classLoader.getResourceAsStream("web.xml")) {
            if(inputStream == null){
                return;
            }
            log.info("web.xml: {}", classLoader.getResource("web.xml"));

            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            Element root = document.getRootElement();
            HashMap<String, ServletConfig> servlets = new HashMap<>();
            {
                List<Element> elems = root.elements("servlet-mapping");
                if (elems != null) {
                    for (Element elem : elems) {
                        ServletConfig config = new ServletConfig();
                        String servletName = elem.element("servlet-name").getStringValue();
                        config.name = servletName;
                        servlets.put(servletName, config);

                        List<Element> patternElems = elem.elements("url-pattern");
                        for(Element pattern : patternElems){
                            config.patterns.add(pattern.getStringValue());
                        }
                        log.info("servletName: {}, servletPattern: {}", servletName, config.patterns);
                    }
                }
            }
            {
                List<Element> elems = root.elements("servlet");
                if (elems != null) {
                    for (final Element elem : elems) {
                        final String servletName = elem.element("servlet-name").getStringValue();
                        final String servletClass = elem.element("servlet-class").getStringValue();
                        final ServletConfig config = servlets.get(servletName);
                        if(config == null){
                            throw new Exception("not found pattern for class: " + servletClass);
                        }
                        log.info("servletName: {}, servletClass: {}", servletName, servletClass);
                        config.clsssName = servletClass;

                        {
                            final List<Element> initparams = elem.elements("init-param");
                            if (initparams != null) {
                                for (Element param : initparams) {
                                    String paramName = param.element("param-name").getStringValue();
                                    String paramValue = param.element("param-value").getStringValue();
                                    log.info("init paramName: {}, paramValue: {}", paramName, paramValue);
                                    config.initParams.put(paramName, paramValue);
                                }
                            }
                        }

                        {
                            final Element multipartElem = elem.element("multipart-config");
                            if(multipartElem != null) {
                                Element location = multipartElem.element("location");
                                Element maxFileSize = multipartElem.element("max-file-size");
                                Element maxRequestSize = multipartElem.element("max-request-size");
                                Element fileSizeThreshold = multipartElem.element("file-size-threshold");
                                if(location != null && maxFileSize != null && maxRequestSize != null
                                        && fileSizeThreshold != null){
                                    config.multipart = new MultipartConfigElement(location.getStringValue(),
                                            Long.parseLong(maxFileSize.getStringValue()),
                                            Long.parseLong(maxRequestSize.getStringValue()),
                                            Integer.parseInt(fileSizeThreshold.getStringValue())
                                            );
                                }
                            }
                        }

                        {
                            final Element asyncSupported = elem.element("async-supported");
                            if(asyncSupported != null){
                                String v= asyncSupported.getStringValue();
                                if(v.startsWith("t") || v.startsWith("T") || v.equals("1")){
                                    config.asyncSupported = true;
                                }
                            }
                        }

                        {
                            final Element startup = elem.element("load-on-startup");
                            if(startup != null){
                                String v= startup.getStringValue();
                                if(v.startsWith("t") || v.startsWith("T") || v.equals("1")){
                                    config.loadOnStartup = true;
                                }
                            }
                        }
                    }
                }
            }

            for (ServletConfig servletConfig : servlets.values()) {
                Class<? extends javax.servlet.http.HttpServlet> cls = (Class<HttpServlet>)
                        Class.forName(servletConfig.clsssName);
                HttpServlet servlet = cls.newInstance();
                ServletRegistration.Dynamic serviceServlet = servletContext.addServlet(servletConfig.name, servlet);
                serviceServlet.addMapping(servletConfig.patterns.toArray(new String[servletConfig.patterns.size()]));
                serviceServlet.setAsyncSupported(servletConfig.asyncSupported);
                serviceServlet.setLoadOnStartup(servletConfig.loadOnStartup?1:0);
                serviceServlet.setInitParameters(servletConfig.initParams);
                if(servletConfig.multipart != null) {
                    serviceServlet.setMultipartConfig(servletConfig.multipart);
                }
            }

        }catch (Exception ex){
            throw new ServletException(ex);
        }
    }
}

兼容原有的listener

也可以通过上一节中的web.xml取出listener, 然后自动配置

@Configuration
public class WebxmlCompatible implements ServletContextInitializer {
	@Override
    public void onStartup(ServletContext servletContext) throws ServletException {
		servletContext.addListener(new MyListener());
	}
}

遇到的坑

struts2不支持servlet 3.1, 导致无法上传文件, 解决办法:
https://blog.csdn.net/wzj_whut/article/details/88219274

猜你喜欢

转载自blog.csdn.net/wzj_whut/article/details/88169006
今日推荐