第 00 章 准备工作(回顾xml配置SpringWeb和Java配置SpringWeb)


前言

当前操作环境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确保配置如下
dawdawd
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" ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201123231901442.png#pic_center) 二、在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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值