Spring那些不得不知的细节

1、SpringMVC拦截器的url-pattern和RequestMapping

案例:

1 url-pattern为/rest/*
2 
3 http请求为:/rest/query/id
4 
5 那么requestMapping为:/query/id

2、post请求方式对MVC控制器的影响

Post请求的四种ContentType:

application/x-www-form-urlencoded   常规表单方式提交

multipart/form-data            带文件上传的表单

application/json              Json格式文本

text/xml                  一般文本,例如webservice

默认情况下大家接收参数用一个pojo,但是它只能接收get请求和post请求的application/x-www-form-urlencoded形式

如果使用json请求,那么请在参数前面加上@RequestBody

如果文件上传,请加上@MultiparyFile

附:json解析配置(jakson2.x)<mvc:annotation-driven>自动注入jakson的bean,转换器是为了保证编码问题

 1 <!-- 处理请求返回json字符串的中文乱码问题 以及映射器、适配器和试图解析器的自动配置-->
 2     <mvc:annotation-driven>
 3         <mvc:message-converters>
 4             <bean class="org.springframework.http.converter.StringHttpMessageConverter">
 5                 <property name="supportedMediaTypes">
 6                     <list>
 7                         <value>application/json;charset=UTF-8</value>
 8                         <value>text/html;charset=UTF-8</value>
 9                     </list>
10                 </property>
11             </bean>
12         </mvc:message-converters>
13     </mvc:annotation-driven>

 3、web中url-pattern中的 / 与 /* 的问题

解:首先大家都知道"/*"可以匹配所有url,包括带扩展名的,一般只用在过滤器上。

而"/"很多人理解成不能拦截带扩展名的,这种理解是错误的!它其实也能拦截“.js”,“.css”,".png"等静态资源的访问。

看官方文档可知,它是tomcat的默认servlet,当其他的url-pattern匹配不上时都会走这个servlet。它除了能够处理静态资源还能够处理HTTP缓存请求,媒体(音频/视频)数据流和文件下载简历。所以如果我们的项目中配置了"/",会覆盖掉tomcat中的default servlet。


tomcat服务器的web.xml配置:

所以当springMVC的前端控制器配置为“/”时,需要在主配置文件中配置放行静态资源。

4、Spring提供了对properties文件读取的支持

配置文件加载属性文件:

<!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:resource/*.properties" />

配置文件中使用:${propertyName}

 1 <!-- 数据库连接池 -->
 2     <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
 3         destroy-method="close">
 4         <property name="url" value="${jdbc.url}" />
 5         <property name="username" value="${jdbc.username}" />
 6         <property name="password" value="${jdbc.password}" />
 7         <property name="driverClassName" value="${jdbc.driver}" />
 8         <property name="maxActive" value="10" />
 9         <property name="minIdle" value="5" />
10     </bean>

Java程序中使用:Spring注解自动注入

1     @Value("${REDIS_KEY_CONTENT}")
2     private String REDIS_KEY_CONTENT;

 5、Spring提供的md5加密,以后再也不用手写了

 6、Spring的IOC容器

  1)如果用了SpringMVC,并且容器分别由spring和springMVC管理,那么存在两个容器,MVC容器可以访问spring的,反之不可以。

  2)MVC容器只能访问父容器的bean,不能访问properties属性。如图

7、SpringMVC中@ResponseBody返回中文乱码问题

默认处理:不经过视图解析器,而是经过转换器转换后直接输出(加<mvc:annotation-driven />)

如果遇到Object对象,默认会采用MappingJackson2HttpMessageConverter(这是jakson2.x的),而且编码自动是UTF-8,所以一般不用配置

如果遇到String对象,默认会采用StringHttpMessageConverter进行解析,但是默认编码是ISO8859-1

配置如下即可解决

<!-- 处理请求返回json字符串的中文乱码问题 以及映射器、适配器和试图解析器的自动配置 -->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <<value>text/html;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

也可以这样,估计是内部自动转换的吧

<!-- 处理请求返回json字符串的中文乱码问题 以及映射器、适配器和试图解析器的自动配置 -->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

 8、在Spring启动后执行立马执行某项任务,比如定时任务。

类似于在系统启动时做操作一样,只不过一个是ServletContextListener,而监听Spring的是InitializingBean

 1 /**
 2  * @Describtion: (执行任务调度). <br/> 
 3  * @date: 2018年6月9日 下午12:46:45 <br/> 
 4  * @author Beats <br/> 
 5  * @version v1.0 <br/>
 6  * @since JDK 1.8
 7  */
 8 @Component
 9 public class SpringContextLisener implements InitializingBean {
10 
11     @Autowired ExamStatusScanner examStatusScanner;
12     
13     @Override
14     public void afterPropertiesSet() throws Exception {
15         //启动
16         examStatusScanner.run();
17     }
18 }

9、配置在spring项目中随时随地获取已经注册好的Bean。

某些情况下,一个类内部需要的对象无法通过正常方式注入进去,比如Quartz通过反射加载job,此时job内就无法使用注解注入。

例外情况代码:

此时就无法通过xml或者注解来注入了

解决方案,手动注入,自定义SpringUtil

1、创建SpringUtil,该类继承ApplicationContextAware

 1 public class SpringUtil implements ApplicationContextAware {
 2 
 3     private static ApplicationContext ac;
 4 
 5     @Override
 6     public void setApplicationContext(ApplicationContext arg0) throws BeansException {
 7         ac = arg0;
 8     }
 9     
10     public static ApplicationContext getApplicationContext() {
11         return ac;
12     }
13     
14     /**
15      * 获取对象
16      * @param name
17      * @return Object 一个以所给名字注册的bean的实例
18      * @throws BeansException
19      */
20     public static Object getBean(String beanName) {
21         Object obj = null;
22         obj = ac.getBean(beanName);
23         return obj;
24     }
25     
26     /**
27      * 如果bean不能被类型转换,相应的异常将会被抛出(BeanNotOfRequiredTypeException)
28      * @param name       bean注册名
29      * @param requiredType 返回对象类型
30      * @return Object 返回requiredType类型对象
31      * @throws BeansException
32      */
33     public static <T> T getBean(String beanName, Class<T> type) {
34         T obj = null;
35         obj = ac.getBean(beanName, type);
36         return obj;
37     }
38     
39     /**
40      * 如果BeanFactory包含所给名称匹配的bean返回true
41      * @param name
42      * @return boolean
43      */
44     public static boolean containsBean(String name) {
45         return ac.containsBean(name);
46     }
47     
48     /**
49      * 判断注册的bean是singleton还是prototype。
50      * 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
51      * @param name
52      * @return boolean
53      * @throws NoSuchBeanDefinitionException
54      */
55     public static boolean isSingleton(String name) {
56         return ac.isSingleton(name);
57     }
58     
59     /**
60      * @param name
61      * @return Class 注册对象的类型
62      * @throws NoSuchBeanDefinitionException
63      */
64     public static Class<?> getType(String name) {
65         return ac.getType(name);
66     }
67 }

2、在Spring中注册他,单例模式

1     <!-- springUtil的创建 ,实现ApplicationContextAware接口 -->
2     <bean id="springUtil" class="henu.util.SpringUtil" scope="singleton" />

之后就可以随时调用。

10、随时随地获取Spring的配置文件键值对

都知道在spring中可以通过@Value来自动注入资源文件中的键值对信息,但是SpringMVC是无法读取到Spring的资源文件的。

所以,可以自定义一个工具类,随时随地获取资源文件信息,并且不用写注解。

1、创建工具类,继承PropertyPlaceholderConfigurer

 1 public class PropertyUtil extends PropertyPlaceholderConfigurer {
 2     private static Map<String,String> propertyMap;
 3 
 4     @Override
 5     protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
 6         super.processProperties(beanFactoryToProcess, props);
 7         propertyMap = new HashMap<String, String>();
 8         for (Object key : props.keySet()) {
 9             String keyStr = key.toString();
10             String value = props.getProperty(keyStr);
11             propertyMap.put(keyStr, value);
12         }
13     }
14 
15     //static method for accessing context properties
16     public static String getProperty(String name) {
17         return propertyMap.get(name);
18     }
19 }

2、在配置文件中注册

是不是很熟悉,跟context:property-placeholder 加载配置文件一样吧

1     <!-- 自定义配置文件获取 -->
2     <bean id="propertyConfigurer" class="henu.util.PropertyUtil" scope="singleton">
3         <property name="location" value="classpath:res.properties"/>
4         <property name="fileEncoding" value="UTF-8"/>
5     </bean>

3、使用:PropertyUtil.getProperty(propName)即可

11、AOP拦截控制器

将AOP配置在SpringMVC中即可,因为父子容器关系。

12、AOP中获取request和response

1、自动注入

1     @Autowired
2     private HttpServletRequest request;
3 
4     @Autowired
5     private HttpServletResponse response;

2、配置监听器

1     <listener>
2         <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
3     </listener>
原文地址:https://www.cnblogs.com/webyyq/p/8886033.html