springmvc中的几个问题
一 url-pattern的问题
- <!-- No mapping found for HTTP request with URI [/WEB-INF/jsp/homePage.jsp] in DispatcherServlet with name 'dispatcher'
- 其中/和/*的区别:
- <url-pattern> / </url-pattern> 不会匹配到*.jsp,即:*.jsp不会进入spring的 DispatcherServlet类.
- <url-pattern> /* </url-pattern> 会匹配*.jsp,会出现返回jsp视图时再次进入spring的DispatcherServlet 类,导致找不到对应的controller所以报404错
- -->
- <servlet-mapping>
- <servlet-name>dispatcher</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
二 访问静态资源的三种方式
(1)最后匹配,此处理器允许当dispatcherServlet的mapping为"/"时利用容器加载静态资源,会处理所有其它请求没有匹配后指向的缺省 servlet.比如的webapp下有一个1.jpg,不写这句无法加载.因为DispatcherServlet拦截“/”,拦截了所有的请求,同时 对*.js,*.jpg的访问也就被拦截了
- <mvc:default-servlet-handler/>
(2)
- <mvc:resources location="/img/" mapping="/img/**"/>
- <mvc:resources location="/js/" mapping="/js/**"/>
- <mvc:resources location="/css/" mapping="/css/**"/
(3)web.xml里添加如下的配置
- <servlet-mapping>
- <servlet-name>default</servlet-name>
- <url-pattern>*.css</url-pattern>
- </servlet-mapping>
- <servlet-mapping>
- <servlet-name>default</servlet-name>
- <url-pattern>*.gif</url-pattern>
- </servlet-mapping>
- <servlet-mapping>
- <servlet-name>default</servlet-name>
- <url-pattern>*.jpg</url-pattern>
- </servlet-mapping>
- <servlet-mapping>
- <servlet-name>default</servlet-name>
- <url-pattern>*.js</url-pattern>
- </servlet-mapping>
三 重复打印各种无用日志
tomcat部署springmvc(什么也没配置的..)显示启动成功,但一直在重复打印下面几句话.浏览器访问可以:
19:49:07.507 [http-bio-8080-exec-10] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
19:49:07.510
[http-bio-8080-exec-10] DEBUG o.s.web.servlet.DispatcherServlet -
DispatcherServlet with name 'dispatcher' processing HEAD request for [/]
19:49:07.510 [http-bio-8080-exec-10] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /
19:49:07.511 [http-bio-8080-exec-10] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Did not find handler method for [/]
19:49:07.511
[http-bio-8080-exec-10] WARN o.s.web.servlet.PageNotFound - No mapping
found for HTTP request with URI [/] in DispatcherServlet with name
'dispatcher'
网上查了不少原因,什么jar包冲突,配置错误,dispatcher路径等,均不管用. 最后多次尝试得到这个结论:
如果配置了tomcat after launch且并没有index.jsp首页就会发生这个情况.若是没有勾选after launch,则有无index.jsp都无所谓,都能正常启动不刷info 和 debug
四 读取配置文件
- <util:properties id="properties" location="classpath:properties/authority.properties"/>
五 spring自带的@Validated校验
controller层:
- @RequestMapping(value = "saleInfoList.json", method = RequestMethod.GET)
- @ResponseBody
- public ApiResult saleInfoList(@Validated CustomerDataParam param, BindingResult bindingResult) {
- if (bindingResult.hasErrors()) {
- return ApiResult.fail(bindingResult.getFieldError().getDefaultMessage());
- }
bean层:

- public class CustomerDataParam extends PrintableBean implements Serializable {
- private static final long serialVersionUID = 8765907263903227625L;
- /**
- * 门店num
- */
- @NotNull(message = "门店num不能为空")
- private String num;
- /**
- * 查询开始日期
- */
- @NotNull(message = "开始日期不能为空")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- private Date beginDate;
- /**
- * 查询结束日期
- */
- @NotNull(message = "结束日期不能为空")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- private Date endDate;
- /**
- * 指标id
- *
- * @see com.xx.xx.enums.xx
- */
- @Min(value = 1, message = "指标id不合法")
- @Max(value = 8, message = "指标id不合法")
- private Integer metricId;

那么在对应的字段出现指定的出错时会有相应的提示
六 @Autowired和@Resource区别
2、@Autowired默认按类型装配(这个注解是属于spring的),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用,如下:
private BaseDao baseDao;
如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。 当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
private BaseDao baseDao;
七 spring bean的作用域和生命周期
Spring Framework支持五种作用域(其中有三种只能用在基于web的)。
在每个Spring IoC容器中一个bean定义对应一个对象实例。 |
|
一个bean定义对应多个对象实例。 |
|
在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各自的bean实例,它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。 |
|
在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。 |
|
在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于web的Spring ApplicationContext情形下有效。 |


- package com.myBeanPostProcessor;
- import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;- /** * Created by balfish on 15-3-29. */
- class MyBeanPostProcessor implements BeanPostProcessor {
- @Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {- System.out.println("postProcessBeforeInitialization 函数被调用");
return o;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {- System.out.println("postProcessAfterInitialization 函数被调用");
return o;
}- }

<!--配置自己的后置处理器,类似过滤器-->
<bean id="myBeanPostProcessor" class="com.myBeanPostProcessor.MyBeanPostProcessor" />
八 分散配置
Spring简化了加载资源文件的配置,可以通过<context:property-placeholder去加载,这个元素的写法如下:
- <context:property-placeholder location="classpath:jdbc.properties"/>
如果想要配置多个properties文件
- <context:property-placeholder location="classpath:jdbc1.properties"/>
- <context:property-placeholder location="classpath:jdbc2.properties"/>
这种方式是不被允许的,一定会出"Could not resolve placeholder"
解决方案:
(1) 在Spring 3.0中,可以写:
- <context:property-placeholder location="xxx.properties" ignore-unresolvable="true"/>
- <context:property-placeholder location="xxx.properties" ignore-unresolvable="true"/>
(2) 但是在Spring 2.5中,<context:property-placeholder>没有ignore-unresolvable属性,所以就不能使用上面的那种方法去配置,可以改如下的格式:

- <bean id="propertyConfigurer"
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="locations">
- <list>
- <value>classpath:/jdbc.properties</value>
- </list>
- </property>
- </bean>

九 springmvc工作原理
上面的是springMVC的工作原理图:
1、客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配DispatcherServlet的请求映射路径(在web.xml中指定),web容器将请求转交给DispatcherServlet.
2、DipatcherServlet接收到这个请求之后将根据请求的信息(包括URL、Http方法、请求报文头和请求参数Cookie等)以及HandlerMapping的配置找到处理请求的处理器(Handler)。
3-4、DispatcherServlet根据HandlerMapping找到对应的Handler,将处理权交给Handler(Handler将具体的处理进行封装),再由具体的HandlerAdapter对Handler进行具体的调用。
5、Handler对数据处理完成以后将返回一个ModelAndView()对象给DispatcherServlet。
6、Handler返回的ModelAndView()只是一个逻辑视图并不是一个正式的视图,DispatcherSevlet通过ViewResolver将逻辑视图转化为真正的视图View。
7、Dispatcher通过model解析出ModelAndView()中的参数进行解析最终展现出完整的view并返回给客户端。
十 spring IOC
inversion of control,控制反转,这是spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。传统的程序开发,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个或是JNDI查询一个),使用完之后还要将对象销毁(比如Connection),对象始终会和其他的接口或类耦合起来
那么IoC是如何做的呢。在spring中,所有的类都会在spring容器中登记,告诉spring它是个什么样的东西,需要什么样的东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所以类的创建,销毁都是由spring控制,也就是说控制对象生命周期的不再是引用它的对象,而是spring。控制反转
IoC的一个重点是在系统运行中,动态地向某个对象提供它所需要的其他对象,这一点是通过DI(Dependency Injection, 依赖注入)来实现的。比如对象A需要操作数据库,以前我们是通过在A中自己编写代码来获得一个Connection对象,有了spring后我们只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。
那么DI是如何实现的呢,java1.3之后一个重要特征是反射(reflection), 它允许程序在运行的时候动态地生成对象,执行对象的方法,改变对象的属性。spring就是通过反射来实现注入的。
十一 spring IOC容器的初始化过程
IOC容器初始化过程分为三个步骤: (1) Resource定位 (2) 载入BeanDefinition (3) 注册这些bean
简单来说,IOC容器的初始化是由refresh方法(FileSystemXmlApplicationContext中的一个构造方法中调用这个refresh方法)来启动的,这个方法标志着IOC容器的正式启动。在我们使用DefaultListableBeanFactory的时候,我们可以清楚地看到step1(Resource资源定位)和step2(载入过程)的的接口调用
- ClassPathResource res =new ClassPathResource("applications.xml");
- DefaultListableBeanFactory factory =new DefaultListableBeanFactory();
- XmlBeanDefinitionReader reader =new XmlBeanDefinitionReader(factory);
- reader.loadBeanDefinitions(res);
Spring把这三个过程分开,并且用不同的模块来完成,比如用相应的ResourceLoader,BeanDefinitionReader等模块,通过这样的设计方式,可以让用户灵活地根据需要来对这些模块进行裁剪和添加
1 Resource定位
这个Resource定位指的是BeanDefinition的资源定位,它由ResourceLoader通过统一的Resource接口来完成,并且这个Resource对各种形式的BeanDefinition都提供了统一的接口。比如在文件系统中的BeanDefinition可以使用FileSystemResource来进行抽象,在类路径中的BeanDefinition可以使用前面提到的ClassPathResource来使用。其实就是让程序定位到定制的Resource资源,比如"application.xml",里面定义了许多bean的信息,所以这个过程就是怎样让程序找到这个文件,然后还要将它封装成resource的类型(Resource是spring用来封装I/O的类)
2 BeanDefinition的载入
这个载入过程就是把我们定义好的Bean表示成Ioc内部的数据结构 - 其实就是BeanDefination。具体来说,这个BeanDefinition就是POJO对象在IOC容器中的抽象,通过这个BeanDefinition定义的数据结构,使得IOC容器能够方便地对POJO对象,也就是Bean,进行管理
3 向IOC容器注册这些Bean
接下来就是通过调用BeanDefinitionRegistry接口来把这些BeanDefinition向Ioc容器中注册,下面是BeanDefinitionRegistry接口的源码
- public interface BeanDefinitionRegistry extends AliasRegistry {
- void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
- throws BeanDefinitionStoreException;
- //移除
- void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
- //得到
- BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
- //判断是否包含
- boolean containsBeanDefinition(String beanName);
- //返回所有在这个registry中定义的bean的名字,如果不存在就返回一个空数组
- String[] getBeanDefinitionNames();
- int getBeanDefinitionCount();
- //判断指定的name是否已经在这个registry中使用,或者判断是否有一个bean的name或者是别名使用的是这个name
- boolean isBeanNameInUse(String beanName);
- }
观察下接口的层次图
可以看到经常使用的DefaultListableBeanFactory正是实现了该接口,可以看下DefaultListableBeanFactory的代码(摘取一部分)
- public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
- implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
- private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
- new ConcurrentHashMap<String, Reference<DefaultListableBeanFactory>>(8);
- private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
- private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
- private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
- private volatile List<String> beanDefinitionNames = new ArrayList<String>(256);
- private volatile Set<String> manualSingletonNames = new LinkedHashSet<String>(16);
- .....
- ........
- }
可以看到,在DefaultListableBeanFactory内部是通过将这些BeanDefination放入HashMap中管理的
4 注意⚠️: 在这个IoC容器初始化的过程中,一般不包含Bean依赖注入的实现。在Spring IoC的设计中,Bean定义的载入和依赖注入是两个独立的过程。依赖注入一般发生在应用第一次通过getBean向IoC容器索取Bean的时候,但是也有例外,那就是设置了lazy-init=false(延迟加载)的时候
lazy-init = "true"表示我们需要这个Bean延迟加载,那么在Ioc初始化的时候就不会实例化这个bean,直到你索要的时候才会实例化(getBean(String name)), 如果没设置,默认是false(不延迟加载),所以默认会初始化这些Bean,可能导致Spring启动速度很慢
如果有两个Bean: bean1, bean2. bean1是延迟加载,bean2没有,bean2里面依赖bean1,然后bean2在容器初始化的时候就实例化了,那么这会导致bean1也会实例化而不是延迟加载。因为容器在实例化bean2的时候,如果bean1没有实例化,那bean2怎么依赖它,所以必须使得bean2也实例化。 因此如果IoC容器在启动的时候创建了那些设置为延迟实例化的bean的实例,也不要奇怪,可能是这些bean在配置的某个地方被注入到了一个非延迟处理化的bean里面
十二 spring AOP
AOP(Aspect - Oriented Programming, 面向切面编程),可以说是OOP(Object - Oriented Programing,面向对象编程)的补充和完善。OOP引入封装,继承和多态性等概念来建立一种对象层次结构,用来模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。这种散步在各处的无关的代码被称为横切(cross - cutting)代码,在OOp设计中,它导致了大量代码的重复,而不利于各个模块的重用。
而AOP技术是利用一种称为"横切"的技术,刨解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为"aspect", 即切面。所谓"切面", 简单滴说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术,AOP把软件系统分为两个部分: 核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似,比如权限,日志,事务处理。实现AOP的技术,主要分为两大类: 一是采用动态代理技术,利用拦截方法的方式,对该方法进行装饰,以取代原有对象行为的执行; 二是采用静态织入的方式,引入特定的语法创建"切面",从而使得编译器可以在编译期间织入有关"切面"的代码。
十三 spring AOP之jdk动态代理和cglib代理的区别
1 JDK动态代理
1. 通过实现 InvocationHandler 接口创建自己的调用处理器;
2. 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
3. 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
4. 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
2 GCLIB代理
1. cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
2. cglib封装了asm,可以在运行期动态生成新的class。
3 两者之间的区别
1. JDK的动态代理必须基于接口,CGLIB没有这个要求
2. java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
4 JDK动态代理和CGLIB字节码生成的区别?
1. JDK动态代理只能对实现了接口的类生成代理,而不能针对类
2. CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法因为是继承,所以该类或方法最好不要声明成final
5 什么情况下会用哪种方式实现动态代理
1. 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2. 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3. 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
6 如何强制使用CGLIB实现AOP?
1. 添加CGLIB库,SPRING_HOME/cglib/*.jar
2. 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
springmvc中的几个问题的更多相关文章
- SpringMvc中的数据校验
SpringMvc中的数据校验 Hibernate校验框架中提供了很多注解的校验,如下: 注解 运行时检查 @AssertFalse 被注解的元素必须为false @AssertTrue 被注解的元素 ...
- 【Spring】SpringMVC中浅析Date类型数据的传递
在控制器中加入如下代码: @InitBinder public void initBinder(ServletRequestDataBinder bin){ SimpleDateFormat sdf ...
- 详解SpringMVC中GET请求
GET请求概述 GET请求,请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接.URL的编码格式采用的是ASCII编码,而不是uniclde,所有的非ASCII字符都要编 ...
- SpringMVC中使用Interceptor拦截器
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...
- 如何在springMVC 中对REST服务使用mockmvc 做测试
如何在springMVC 中对REST服务使用mockmvc 做测试 博客分类: java 基础 springMVCmockMVC单元测试 spring 集成测试中对mock 的集成实在是太棒了!但 ...
- springMVC 返回类型选择 以及 SpringMVC中model,modelMap.request,session取值顺序
springMVC 返回类型选择 以及 SpringMVC中model,modelMap.request,session取值顺序 http://www.360doc.com/content/14/03 ...
- SpringMVC中使用Cron表达式的定时器
SpringMVC中使用Cron表达式的定时器 cron(定时策略)简要说明 顺序: 秒 分 时 日 月 星期 年份 (7个参数,空格隔开各个参数,年份非必须参数) 通配符: , 如果分钟位置为* 1 ...
- SpringMVC中使用Json传数据
在web项目中使用Json进行数据的传输是非常常见且有用的,在这里介绍下在SpringMVC中使用Json传数据的一种方法,在我的使用中,主要包括下面四个部分(我个人喜好使用maven这类型工具进行项 ...
- springmvc 中controller与jsp传值
参考:springmvc 中controller与jsp传值 springMVC:将controller中数据传递到jsp页面 jsp中,死活拿不到controller中的变量. 花了半天,网上列出各 ...
- 在Springmvc中获取properties属性
一些关键的属性一般都会拿出来作为配置,比如数据库连接等.在springmvc中也提供了获取property的类,比如@Value来获取.我接触spring很浅,基本上都是百度的问题解决方法,百度到@v ...
随机推荐
- jquery拖拽效果
<!doctype html><html lang="en"><head> <meta charset="utf-8" ...
- SQLServer乱码问题的分析及解决方法(中文字符被存入数据库后,显示为乱码)
注:本文为个人转存,原文地址:http://blog.csdn.net/qiuyu8888/article/details/8021410 问题:SQL版在使用过程中有时会出现乱码,我的症状是中文字符 ...
- 解决Firefox访问12306"连接不受信任"的问题
用Firefox访问12306.cn, 总是提示"This Connection is Untrusted", 曾经有个"Add Exception" 按钮, ...
- 监控自定义信息 —— ESFramework 4.0 快速上手(10)
在ESFramework 4.0 进阶(02)-- 核心:消息处理的骨架流程一文中,我们介绍了通过挂接IMessageSpy到骨架流程,我们就可以监控到所有收发的消息.由于Rapid引擎已经为我们组装 ...
- (转载)app ico图标字体制作
图标字体化浅谈 在做手机端Web App项目中,经常会遇到小图标在手机上显示比较模糊的问题,经过实践发现了一种比较好的解决方案,图标字体化.在微社区项目中,有很多小的Icon(图标),如分享.回复 ...
- java中的Volatile 变量
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”:与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少, ...
- SQL 课程 连接查询
今天,我主要是对前面所学习过的子查询进行了复习,然后学习了连接查询join on 的内容. 如: select renyuan.code,name,age ,sex , bumen.bname,bce ...
- 重复T次的LIS的dp Codeforces Round #323 (Div. 2) D
http://codeforces.com/contest/583/problem/D 原题:You are given an array of positive integers a1, a2, . ...
- C# 调用C++ DLL 的类型转换
//C#调用C++的DLL搜集整理的所有数据类型转换方式,可能会有重复或者多种方案,自己多测试 //c++:HANDLE(void *) ---- c#:System.IntPtr //c++:Byt ...
- 发现一个c++ vector sort的bug
在开发中遇到一个非常诡异的问题:我用vector存储了一组数据,然后调用sort方法,利用自定义的排序函数进行排序,但是一直都会段错误,在排序函数中打印参加排序的值,发现有空值,而且每次都跟同一个数据 ...