无xml的SpringMVC
简单的嵌入式 Tomcat + 无Xml + SpringMVC 主要代码示例;不建议当作正式服务使用,虽然我已无BUG运行数月,但不确定会不会发生未知异常;文中大部分有注释;如有不懂百度即可,此文不做过多赘述;
版本(都是最新的):
Spring6+
Tomcat11+
主要配置 ApplicationMain(Tomcat的启动代码)
public class Webapp {
static final Logger LOGGER = Logger.getLogger(Webapp.class.getName());
static void testPort(int port) throws IOException {
// 检测端口是否被占用
ServerSocket socket = null;
try {
socket = new ServerSocket(port);
} catch (IOException e) {
System.err.println(port + " 端口已被占用");
System.exit(0);
return;
} finally {
socket.close();
}
}
private static File createTempDir(String prefix) {
try {
File tempDir = Files.createTempDirectory(prefix + ".").toFile();
tempDir.deleteOnExit();
return tempDir;
} catch (IOException var3) {
throw new RuntimeException("Unable to create tempDir. java.io.tmpdir is set to " + System.getProperty("java.io.tmpdir"), var3);
}
}
private static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
} catch (Throwable var3) {
var3.printStackTrace();
}
return cl;
}
public static void main(String[] args) {
int port = 8080;
try {
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("system.properties");
Properties properties = new Properties();
properties.load(inputStream);
String p = properties.getProperty("port");
if(StringUtil.isNotEmpty(p)) {
port = Integer.parseInt(p);
}
LOGGER.warning("当前端口:"+port);
if (args.length > 0) {
port = Integer.parseInt(args[0]);
}
testPort(port);
// Windows系统上运行必须要有webapps文件夹,不然启动不了,辣鸡!
/*
String osName = System.getProperties().getProperty("os.name");
if (osName.toLowerCase().contains("windows")) {
String path = Webapp.class.getResource("/").getPath() + "/webapps";
File file = new File(path);
if (!file.exists()) {
file.mkdir();
}
}
*/
//Registry.disableRegistry();
Tomcat tomcat = new Tomcat();
//Tomcat工作目录
//String tomcatBaseDir = createTempDir("tomcat[" + port + "]").getAbsolutePath();
String tomcatBaseDir = getDefaultClassLoader().getResource("").getPath();
tomcat.setBaseDir(tomcatBaseDir);
LOGGER.info("Tomcat baseDir:" + tomcatBaseDir);
//连接器配置
//@see https://blog.csdn.net/chanrenyuan/article/details/46869475
Connector connector = new Connector(Http11NioProtocol.class.getName());
connector.setPort(port);
connector.setURIEncoding("UTF-8");
//connector.setProperty("address", InetAddress.getByName("localhost").getHostAddress());
connector.setProperty("maxThreads", "200");
connector.setProperty("maxConnections", "1000");//最大并发socket
connector.setProperty("acceptCount", "10000");//请求访问队列数
connector.setProperty("connectionTimeout", "30000");
connector.setProperty("maxHeaderCount", "100");//最多支持的header数量
connector.setProperty("maxParameterCount", "1000");//最多支持的参数数量
//connector.setUseBodyEncodingForURI(false);//是否用contentType中的编码来解码
//将此属性设置为true以使 Tomcat 使用接收请求的 IP 地址来确定将请求发送到的主机。
//connector.setUseIPVHosts(false);
connector.setProperty("server", "XingZhen");
//connecto\
// r.getProtocolHandler(); //自定义协议处理,如果需要
connector.setProperty("bindOnInit", "false"); // 全部启动完成后才支持请求
connector.setProperty("processorCache", "100"); //支持缓存对象数量,默认200
connector.setProperty("socket.directBuffer", "false");//是否使用JDK的Byte缓冲
/*
//SSL
//更改Scheme
connector.setScheme("https");
connector.setSecure(true);
//跳转连接器
Connector cc = new Connector(Http11NioProtocol.class.getName());
cc.setScheme("http");
cc.setPort(8080);
cc.setRedirectPort(443);
AbstractHttp11JsseProtocol<?> protocol = (AbstractHttp11JsseProtocol<?>) connector.getProtocolHandler();
protocol.setSSLEnabled(true);
protocol.setSslProtocol("TLS");
protocol.setKeystoreFile("youle123456.p12");
protocol.setKeystoreType("PKCS12");
protocol.setKeystorePass("youle123456");
protocol.setKeyAlias("tomcat");
*/
tomcat.setConnector(connector);
//tomcat.setHostname("192.168.31.186");
tomcat.getHost().setAutoDeploy(false);
String contextPath = "";
Charset uriEncoding = StandardCharsets.UTF_8;
//String contextDocBase = createTempDir("contextDocBase").getAbsolutePath();
//String contextDocBase = Webapp.class.getClassLoader().getResource("").getPath();
String contextDocBase = getDefaultClassLoader().getResource("").getPath();
LOGGER.info("contextDocBase:" + contextDocBase);
//tomcat.setAddDefaultWebXmlToWebapp(false);
StandardContext context = (StandardContext) tomcat.addWebapp(contextPath, contextDocBase);
//context.setParentClassLoader(getDefaultClassLoader());
context.setRequestCharacterEncoding(uriEncoding.name());
//不扫描 某些配置
((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
context.setReloadable(true);
//TODO 开起文件上传支持 (HttpServletRequest.Part); Servlet3.0+支持 @MultipartConfig
context.setAllowCasualMultipartParsing(true);
//WebResourceRoot root = new StandardRoot(context);
//root.addPreResources(new DirResourceSet(root, "/", contextDocBase, "/"));
//context.setResources(root);
ErrorPage ep = new ErrorPage();
//ep.setErrorCode(500);
ep.setLocation("/error");
context.addErrorPage(ep);
//tomcat.enableNaming();
tomcat.start();
tomcat.getServer().await();
} catch (Exception e) {
System.err.println("启动错误 Error:" + e.getMessage());
System.err.println("命令启动时第一个参数为端口号(默认端口" + port + ")");
e.printStackTrace();
}
}
}
主要配置 WebApplicationInitializer
public class MyWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
//druid链接池的监控配置
ServletRegistration.Dynamic ctx = servletContext.addServlet("DruidServlet", StatViewServlet.class);
ctx.setInitParameter("loginUsername", "admin");
ctx.setInitParameter("loginPassword", "123456");
ctx.addMapping("/druid/*");
}
// 返回Spring应用根容器中定义的beans,对应ContextLoaderListener,是Spring根容器
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{ RootConfig.class };
}
// 返回Spring MVC应用容器中定义的beans,对应DispatcherServlet中加载的bean
// Spring MVC容器是根容器的子容器,子容器可以看到根容器中定义的beans,反之不行
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{ ServletConfig.class }; //StatViewServlet.class
}
// 指定映射拦截URL
protected String[] getServletMappings() {
return new String[]{ "/" };
}
// 修改 通过重写此方法修改DispatcherServlet的名称,对应<servlet-name></servlet-name>标签
@Override
protected String getServletName() {
return super.getServletName();
}
//@Override
//protected Filter[] getServletFilters() {
// return new Filter[]{new WebStatFilter()};
//}
}
主要配置 RootConfig
@Configuration
//@ImportResource(locations = "classpath:config/app.xml")
@ComponentScan({"config", "service"}) //扫描的包路径
@PropertySource({"classpath:system.properties"})
@EnableTransactionManagement
public class RootConfig {
private final Logger logger = LoggerFactory.getLogger(RootConfig.class);
@Bean
public ApplicationContextAware applicationContextAware(ApplicationContext ctx) {
return args -> {
System.err.println("beans:");
String[] beanNames = ctx.getBeanDefinitionNames();
//Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.err.println("---> " + beanName);
}
logger.warn("Bean Count: {}", ctx.getBeanDefinitionCount());
logger.warn("==========- WEB服务启动完成 -==========");
};
}
}
主要配置 ServletConfig
@Configuration
@EnableWebMvc //@EnableWebMvc 同等 WebMvcConfigurationSupport
@ComponentScan("controller") //Controller控制器的包路径
public class ServletConfig {}
pom.xml:Spring,Tomcat
<!-- 此处用的版本: -->
<spring.version>6.1.8</spring.version>
<tomcat>11.0.0-M20</tomcat>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
<!--Tomcat-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>${tomcat}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>${tomcat}</version>
</dependency>