文章目录
前言
当前操作环境jdk1.8,maven3.6,tomcat9.0.19
通过xml配置SpringWeb项目
正文
使用idea进行操作.
首先通过idea#file->New->Project->Maven,直接选择next
设置项目名和地址点击finish
设置pom文件
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>Test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>//确保已经设置为war
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
</dependencies>
右键项目选择open Module Setting
选择Modules选择添加icon
添加web选项
点击添加icon确保配置如下
Tomcat配置如下
上面的Application context添不添加无所谓,主要根据<url-pattern>/</url-pattern>'判断
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
添加web.xml内容
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>springMvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
添加spring-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="org.rule" use-default-filters="true">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
添加spring-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="org.rule" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
java类
@Service
public class HelloService {
public String hello(){
return "hello 世界";
}
}
@RestController
public class HelloController {
HelloService service;
public HelloController(HelloService service) {
this.service = service;
}
//produces = "text/html;charset=utf8"避免中文输出乱码
@GetMapping(value = "/", produces = "text/html;charset=utf8")
public String hello() {
return service.hello();
}
}
启动
问题处理
tomcat乱码解决
一、修改Tomcat的conf的server.xml文件加上 URIEncoding="UTF-8"  二、在tomcat的bin 目录下的catalina.bat 配置文件中,添加以下设置set “JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS% -Dfile.encoding=UTF-8”
三、控制台打印出现乱码。cmd输入regedit 进入注册表,找到HKEY_CURRENT_USER→Console→Tomcat(如果你改了tomcat的标题栏,这里就是你打开的命令窗口的名字),找到CodePage项,没有则创建,更改值为十进制的65001,点击确定。
如果没有找到tomcat新建一个Tomcat项,里面选择DWORD,值填写65001
四、修改tomcat/apache-tomcat-7.0.92/conf/logging.properties把UTF-8改成GBK
玩转 IDEA 之 Maven依赖自动提示
输入我们想要的依赖,按Ctrl+Alt +空格,根据提示自动生成我们想要的依赖
2、快速搜索
自动提示功能有时候会不太灵敏,我们还可以使用快速搜索功能:
按Alt+Insert,选择Dependenc:
参考链接
0.1-tomcat乱码解决
0.1玩转 IDEA 之 Maven依赖自动提示
通过java配置SSM
正文
创建项目过程同上,不再赘述,不再添加web选项,依然添加tomcat,不再添加web.xml,spring-context.xml,spring-config.xml
修改pom.xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
</dependencies>
新增四个类,并修改HelloController
public class WebInit implements WebApplicationInitializer {
public void onStartup(javax.servlet.ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(ContextConfig.class, ServletConfig.class);
context.setServletContext(servletContext);
ServletRegistration.Dynamic springMvc = servletContext.addServlet("springMvc", new DispatcherServlet(context));
springMvc.addMapping("/");
//为正数表示容器将在In this case, the container must instantiate and
//initialize the Servlet during the initialization phase of the ServletContext
//(ServletContext的初始化阶段实例化和初始化Servlet)初始化和实例化
springMvc.setLoadOnStartup(1);
}
@ComponentScan(basePackages = "org.rule",
useDefaultFilters = true,
excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class))
public class ContextConfig {
}
@ComponentScan(basePackages = "org.rule",
useDefaultFilters = false,
includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class))
public class ServletConfig extends WebMvcConfigurationSupport {
// ant风格/**,**代表任意多层路径的任意资源名称
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
}
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
//For example, {{@code "/"}, {@code "classpath:/META-INF/public-web-resources/"}}
//映射静态资源uri对应的location
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
//添加所有SerializerFeature,只添加BrowserCompatible,虽然可以避免特殊字符转换为
//unicode,但是中文依旧会被自动转换为unicode,有空一个个试看到底是哪个特性决定的转换中文
converter.getFastJsonConfig().setSerializerFeatures(SerializerFeature.values());
converters.add(converter);
}
}
@RestController
public class HelloController {
HelloService helloService;
public HelloController(HelloService helloService) {
this.helloService = helloService;
}
@GetMapping(value = "/", produces = "text/html;charset=UTF-8")
public String hello() {
return helloService.hello();
}
@GetMapping(value = "/data", produces = "application/json;charset=utf8")
public List<String> data() {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
list.add("test(测试):>>>" + i);
}
return list;
}
}
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
效果展示
问题处理
Maven Scope
scope:
1.test范围是指测试范围有效,在编译和打包时都不会使用这个依赖
2.compile范围是指编译范围内有效,在编译和打包时都会将依赖存储进去
3.provided依赖,在编译和测试过程中有效,最后生成的war包时不会加入 例如:
servlet-api,因为servlet-api tomcat服务器已经存在了,如果再打包会冲突
4.runtime在运行时候依赖,在编译时候不依赖
5.0import只能在dependencyManagement中使用,且type为pom类型。
dependencyManagement里配置并不会实际引入,只是为了版本管理,实际引入需要直接在dependencies中添加。
默认依赖范围是compile
scope import example:
spring-boot-dependencies-2.2.11.RELEASE.pom
<dependencyManagement>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.11.RELEASE</version>
</dependency>
<dependencyManagement>
pom.xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.11.RELEASE</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
这样pom.xml根据groupId和artifactId的对应从导入进来的spring-boot-dependencies-2.2.11.RELEASE.pom的dependencyManagement中找到对应的并按照version导入依赖
fastjson数据导出到游览器问题处理
为GetMapping设置produces值为"text/html;charset=utf8",主要是charset=utf8用来通知游览器数据已什么编码解释,"text/html"通知游览器用什么格式展示数据.
通过extend WebMvcConfigurationSupport接口,重写configureMessageConverters添加自定义HttpMessageConverter
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
//添加所有SerializerFeature,只添加BrowserCompatible,虽然可以避免特殊字符转换为
//unicode,但是中文依旧会被自动转换为unicode,有空一个个试看到底是哪个特性决定的转换中文
converter.getFastJsonConfig().setSerializerFeatures(SerializerFeature.values());
converters.add(converter);
}
如何通过WebApplicationInitializer初始化web应用
SPI ,全称为 Service Provider Interface,是一种服务发现机制
官方的解释:
为了支持可以不使用web.xml。提供了ServletContainerInitializer,
它可以通过SPI机制,当启动web容器的时候,会自动到添加的相应jar包下找到META-INF/services下以ServletContainerInitializer的全路径名称命名的文件,
它的内容为ServletContainerInitializer实现类的全路径,将它们实例化
WebApplicationInitializer位于org.springframework:spring-web包下,这个jar包的META - INF/services下定义了一个
javax.servlet.ServletContainerInitializer文件内容:
org.springframework.web.SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
List<WebApplicationInitializer> initializers = Collections.emptyList();
if (webAppInitializerClasses != null) {
initializers = new ArrayList<>(webAppInitializerClasses.size());
for (Class<?> waiClass : webAppInitializerClasses) {
// Be defensive: Some servlet containers provide us with invalid classes,
// no matter what @HandlesTypes says...
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer)
ReflectionUtils.accessibleConstructor(waiClass).newInstance());
}
catch (Throwable ex) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
}
}
}
}
if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
}
servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
javax.servlet提供了@HandlesTypes注解,添加需要处理的类放入webAppInitializerClasses集合中
servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
//在前面的验证判断结束后开始调用onStartup方法
initializer.onStartup(servletContext);
}
这样就调用了自定义的初始化类WebInit,通过AnnotationConfigWebApplicationContext初始化了上下文,并确定了映射地址
参考链接
maven_provided说明
深入理解SPI机制
Spring中WebApplicationInitializer的理解
Spring @Bean标注在有参方法上
最近几个新版本会把括号序列化成unicode字符 #2386