SpringMVC之响应数据传出

Spring MVC除了在原生的request和session外还能怎么样把数据带给页面

1) 可以在方法处传入Map,或者Model或者ModelMap。给这些参数里面保存的所有数据都会放在所有的数据都会放在请求域中。可以在页面中获取

在PageContext、Request、Session、Application
Map(interface(jdk)) ModelMap(class)
Model(interface(spring))
2) 方法的返回值可以变为ModeAndView类型
既包含视图信息(页面地址)也包含模型数据(给页面带的数据)
而且数据是放在请求域中
request、session、application
3) Spring MVC提供了一种可以临时给Session域中保存数据的方式
使用一个注解 @SessionAttributes(只能标注在类上)
给BindingAwareModelMap中保存的数据,同时给session中放一份

HiddenHttpMethodFilter (REST)

概述

REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。
它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。
目前在三种主流的Web服务实现方案中,因为REST模式的Web服务与复杂的SOAP和XML-RPC对比来讲明显的更加简洁,越来越多的web服务开始采用REST风格设计和实现。
例如,Amazon.com提供接近REST风格的Web服务进行图书查找;雅虎提供的Web服务也是REST风格的。

SpringMVC之@RequestMapping

@RequestMapping 映射请求注解

  • SpringMVC使用@RequestMapping注解为控制器指定可以处理哪些 URL 请求
  • 在控制器的类定义及方法定义处都可标注 @RequestMapping
    • 标记在类上:提供初步的请求映射信息。相对于 WEB 应用的根目录
    • 标记在方法上:提供进一步的细分映射信息。相对于标记在类上的 URL。
  • 若类上未标注 @RequestMapping,则方法处标记的 URL 相对于 WEB应用的根目录

    作用:DispatcherServlet 截获请求后,就通过控制器上 @RequestMapping 提供的映射信息确定请求所对应的处理方法。

SpringMVC之HelloWorld

Servlet启动加载,Servlet原本是第一次访问创建对象
load-on-startup: 服务器启动的时候创建对象,值越小优先级越高

SpringMVC概述

  • Spring 为展现层提供的基于 MVC 设计理念的优秀的 Web 框架,是目前最主流的 MVC 框架之一。
  • Spring3.0 后全面超越 Struts2,成为最优秀的 MVC 框架。
  • Spring MVC 通过一套 MVC 注解,让 POJO(Plain Old Java Object) 成为处理请求的控制器,而无须实现任何接口。
  • 支持 REST 风格的 URL 请求。
  • 采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性。

Spring和JavaWeb

Spring和JavaWeb整合使用

  1. Spring来控制事务(DAO[JDBCTemplate])
  2. 所有组件AutoWired
  3. 管理数据库

整合步骤

  1. 导包

  2. 写配置

    1. 将所有组件加入容器中,并能正确获取
      @Controller:Servlet层,目前不能标注在Servlet层
      @Service: 业务逻辑层
      @Repository Dao层
      @Component 其他组件

    2. 每个组件之间自动装配

    3. 配置出声明式事务
      事务管理器控制数据库连接池
      IOC容器创建和销毁要在合适的时机完成

      1
      2
      3
      4
      5
      6
      项目启动{
      ioc创建
      }
      项目销毁{
      IOC销毁
      }
  3. 测试

Spring 源码

Spring AOP

动态代理
多层切面在环绕通知,内部切面的返回值会影响外部的返回值

Spring IOC

  1. IOC是一个容器
  2. 容器启动的时候创建所有单实例对象
  3. 可以直接从容器中获取到这个对象

问题

1) ioc容器的启动过程?启动时间都做了什么?什么时候创建所有单实例bean
2) ioc是如何创建单实例bean,并如何管理,这些Bean保存在哪里

调试

  1. ioc = new ClassPathXmlApplicationContext(“application.xml”);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    1. this(new String[] {configLocation}, true, null);
    2.
    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
    throws BeansException {

    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
    refresh();
    }
    }

refresh();运行后所有Bean创建完成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.
initMessageSource();

// Initialize event multicaster for this context.
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
onRefresh();

// Check for listener beans and register them.
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();
}

catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();

// Reset 'active' flag.
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}
}
}

解析xml配置文件并创建所有配置文件下创建的Bean,将这些信息保存起来 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
initMessageSource(); 支持国际化
initApplicationEventMulticaster(); 初始化事件转换器
onRefresh(); 留给子类的方法,方便自定义容器
finishBeanFactoryInitialization(beanFactory); 初始化单实例Bean
调用上一个方法后进入, AbstractApplicationContext类中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}

// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}

// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);

// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();

// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}

beanFactory.preInstantiateSingletons(); 初始化单实例
DefaultListableBeanFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}


//拿到所有Bean创建的名字


List<String> beanNames;
synchronized (this.beanDefinitionMap) {
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
beanNames = new ArrayList<String>(this.beanDefinitionNames);
}


//按顺序创建Bean
for (String beanName : beanNames) {

//根据BeanId获取Bean的定义信息
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//如果Bean是单实例并且不是懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//是否工厂bean(即是否实现FactoryBean)
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
//创建Bean的细节
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
}

getBean调用的是doGetBean(name, null, null, false);(位于AbstractBeanFactory)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
//先获取Bean名
final String beanName = transformedBeanName(name);
Object bean;

// Eagerly check singleton cache for manually registered singletons.
//先从已经创建的Bean中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}

if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}

try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// Guarantee initialization of beans that the current bean depends on.
//拿到 才创建当前Bean之前需要提前创建的Bean,depends-on,有就循环创建
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException("Circular depends-on relationship between '" +
beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}
}

// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}

// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}

DefaultSingletonBeanRegistry类
getSingleton 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
* Return the (raw) singleton object registered under the given name,
* creating and registering a new one if none registered yet.
* @param beanName the name of the bean
* @param singletonFactory the ObjectFactory to lazily create the singleton
* with, if necessary
* @return the registered singleton object
*/
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
//先将Bean get出来
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while the singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
singletonObject = singletonFactory.getObject();
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
//添加创建的bean
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}

1
2
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
  • addSingleton方法(创建的Bean最终保存)
    1
    2
    3
    4
    5
    6
    7
    8
    protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
    this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
    this.singletonFactories.remove(beanName);
    this.earlySingletonObjects.remove(beanName);
    this.registeredSingletons.add(beanName);
    }
    }

BeanFacory总结

BeanFactory和ApplicationContext的区别?
ApplicationContext是BeanFactory的子接口
BeanFactory : Bean工厂,赋值Bean的创建,容器中保存的单例Bean其实是一个map
ApplicationContext:容器接口,负责容器容器功能的实现(可以基于BeanFactory创建好的对象之上完成强大的容器)
容器可以从map获取这个Bean,并且aop,DI(依赖注入)这些功能是在ApplicationContext接口下的这些类里面
BeanFactory最底层的接口,ApplicationContext留给程序员使用的ioc容器接口
Spring最大的模式就是工厂模式

Spring 声明式事务

事务概述

  • 在JavaEE企业级开发的应用领域,为了保证数据的 完整性和一致性 ,必须引入数据库事务的概念,所以事务管理是企业级应用程序开发中必不可少的技术。
  • 事务就是一组由于逻辑上紧密关联而合并成一个整体(工作单元)的多个数据库操作,这些操作 要么都执行,要么都不执行
  • 事务的四个关键属性(ACID)
    • 原子性 (atomicity):“原子”的本意是“不可再分”,事务的原子性表现为一个事务中涉及到的多个操作在逻辑上缺一不可。事务的原子性要求事务中的所有操作要么都执行,要么都不执行。
    • 一致性 (consistency):“一致”指的是数据的一致,具体是指:所有数据都处于满足业务规则的一致性状态。一致性原则要求:一个事务中不管涉及到多少个操作,都必须保证事务执行之前数据是正确的,事务执行之后数据仍然是正确的。如果一个事务在执行的过程中,其中某一个或某几个操作失败了,则必须将其他所有操作撤销,将数据恢复到事务执行之前的状态,这就是回滚。
    • 隔离性 (isolation):在应用程序实际运行过程中,事务往往是并发执行的,所以很有可能有许多事务同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。隔离性原则要求多个事务在并发执行过程中不会互相干扰。
    • 持久性(durability):持久性原则要求事务执行完成后,对数据的修改永久的保存下来,不会因各种系统错误或其他意外情况而受到影响。通常情况下,事务对数据的修改应该被写入到持久化存储器中。

拓展: 在大数据中的新型数据库中存在严格一致性


Leetcode/leetcode45

45. Jump Game II

参考
题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public int jump(int[] nums) {
int dept=0;
int cursor = 0,i=0;
while(cursor<nums.length-1) {
dept++;
int limit = cursor;
for(;i<=limit;i++) {
cursor = Math.max(cursor, i+nums[i]);
}
}

return dept;

}
}

44. Wildcard Matching

44. Wildcard Matching(通配符匹配)

参考资料

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 public boolean isMatch(String s, String p) {
int i=0,j=0,iStar=-1,jStar=-1,pLen=p.length(),sLen=s.length();

while(i<sLen) {
if(j<pLen&&(s.charAt(i)==p.charAt(j)||p.charAt(j)=='?')) {
i++;
j++;
}else if(j<pLen&&p.charAt(j)=='*'){
iStar = i;
jStar = j++;
}else if(jStar>=0){
i = ++iStar;
j = jStar+1;
}else {
return false;
}
}
while(j<pLen&&p.charAt(j)=='*')j++;
return j==pLen;
}

[8, 2,4,4,4,9,5,2,5, 8,8,0,8,6,9, 1,1,6,3,5,1,2,6,6, 0,4,8,6,0,3 ,2,8,7,6,5 ,1,7,0,3,4, 8,3,5,9 ,0,4,0,1,0,5,9,2,0,7,0,2,1,0,8,2,5,1,2,3,9,7,4,7,0,0,1,8,5,6,7,5,1,9,9,3,5,0,7,5]

43. Multiply Strings

43. Multiply Strings(大数乘法)

思路

模拟乘法运算即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
StringBuffer res = new StringBuffer();
public String multiply(String num1, String num2) {
if(num1.charAt(0)=='0'||num2.charAt(0)=='0') {

return "0";
}
//为了减少计算,把长度比较小的作为乘数
String tmp;
if(num1.length()<num2.length()) {
tmp = num1;
num1 = num2;
num2 = tmp;
}


for(int i = num2.length()-1; i >= 0; i--) {
int j = num2.charAt(i)-'0';
while(j>0) {
plus(num1, num2.length()-i-1);
j--;
}
}

return res.toString();
}

public void plus(String num1, int k) {
//System.out.println("k="+k+"res="+res.toString());
if(res.length()==0) {
res.append(num1);
for(int i=0;i<k;i++)res.append('0');
return;
}
int quotient = 0;
int i,j;
//遇到的错误②
for(i=res.length()-k-1, j=num1.length()-1; i>=0||j>=0; i--,j--) {
int sum = (i<0?0:(res.charAt(i)-'0')) + (j<0?0:(num1.charAt(j)-'0'))+quotient;

quotient = sum/10;
if(i>=0) {
res.setCharAt(i, (char) (sum%10 + '0'));
}else {
res.insert(0, sum%10);
}
//System.out.println("quotient="+quotient+"i="+i+"sum="+sum+"res="+res.toString());
//System.out.println((char) (sum%10 + '0'));
}


if(quotient!=0) {
res.insert(0, quotient);
}

//System.out.println("k="+k+"res:"+res.toString());
}

遇到的问题

  1. 忽略num1=”0”或num2=”0”的情况
  2. 进位错误,原因是在标注2的位置的一部分放到外面导致进位错误
  3. 还有一个错误是字符与数字之间的转换,在StringBuffer中可以直接插入整数,无须转换为字符
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×