{"id":14983005,"url":"https://github.com/vonzhou/springinaction3","last_synced_at":"2025-04-09T17:25:13.391Z","repository":{"id":47780571,"uuid":"55063485","full_name":"vonzhou/SpringInAction3","owner":"vonzhou","description":"Code of Spring In Action 3rd， Spring学习笔记","archived":false,"fork":false,"pushed_at":"2023-12-17T23:32:14.000Z","size":57933,"stargazers_count":169,"open_issues_count":5,"forks_count":84,"subscribers_count":24,"default_branch":"master","last_synced_at":"2025-04-02T10:47:00.030Z","etag":null,"topics":["bean","java","spring","spring-mvc"],"latest_commit_sha":null,"homepage":"http://vonzhou.com","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vonzhou.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-03-30T13:02:51.000Z","updated_at":"2025-01-16T01:31:24.000Z","dependencies_parsed_at":"2024-09-24T11:01:08.767Z","dependency_job_id":"9bdcf4b3-e344-4aa7-a946-8b2413a283e9","html_url":"https://github.com/vonzhou/SpringInAction3","commit_stats":{"total_commits":26,"total_committers":4,"mean_commits":6.5,"dds":0.5,"last_synced_commit":"bc3720c593c45c11dbd13955a148edb51508854a"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vonzhou%2FSpringInAction3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vonzhou%2FSpringInAction3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vonzhou%2FSpringInAction3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vonzhou%2FSpringInAction3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vonzhou","download_url":"https://codeload.github.com/vonzhou/SpringInAction3/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248075831,"owners_count":21043653,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bean","java","spring","spring-mvc"],"created_at":"2024-09-24T14:06:34.039Z","updated_at":"2025-04-09T17:25:13.371Z","avatar_url":"https://github.com/vonzhou.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spring In Action \n---\n\nupdate 2016.8.12 使用freemarker模板引擎\n\n**2016.3.31  阅读《Spring实战3rd》**\n\n之前间歇的阅读过，但是只是停留在理解的层面上，想要把每个例子跑通也需要一定的折腾。\n\n注：每个示例都是一个单独的Maven Project。\n\n**2016.7.12 update**\n\n* 集成mybatis\n* Spring集成JUnit单元测试   [spitter-persistence-mybatis](https://github.com/vonzhou/SpringInAction3/tree/master/spitter-persistence-mybatis)\n* 从Spring MVC中返回json，[spitter-web](https://github.com/vonzhou/SpringInAction3/tree/master/spitter-web)中SpitterController\n\n## 1. Spring之旅\n\n* 依赖注入\n* AOP\n* bean的初始化过程\n* spring容器\n* Spring还有很多值得学习的框架，如安全\n\n**跑起来√** [knights](https://github.com/vonzhou/SpringInAction3/tree/master/knights/src/main/java/com/vonzhou/springinaction/knights)\n\n## 2. 装配Bean\n\n* “initialization on demand holder”创建单例模式的理解,参考 [Initialization-on-demand holder idiom](https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom)\n* Spring中单例的概念限于Spring上下文中，遵守约定\n* 内部bean适用于setter注入和构造器注入，内部bean不能被复用\n* SpEL表达式\n\n**跑起来√** [springidol](https://github.com/vonzhou/SpringInAction3/tree/master/springidol)\n\n## 3. 最小化Spring XML配置\n\n* 4 种自动装配 byName, byType, contructor, autodetect\n* 可以在一个应用上下文中定义多个配置文件，每个配置文件设置自己的默认自动装配策略(default-autowire)\n* 如果使用constructor自动装配策略，就不能混合使用constructor-arg\n* 注解方式可以实现更细粒度的自动装配，Spring容器默认禁用注解装配，要在配置文件中开启\n* \\\u003ccontext:component-scan\u003e 配置自动扫描\n* 在基于Java的配置中使用@Configuration注解的Java类，等价于XML配置中的\\\u003cbeans\u003e元素\n\n**跑起来√** [springidol-autodiscovery](https://github.com/vonzhou/SpringInAction3/tree/master/springidol-autodiscovery)\n\n## 4. 面向切面Spring\n\n* Spring只支持方法连接点\n* 体会切面的应用场景\n* before, after, around advice\n* 为advice传递参数\n* introduction为已有的接口引入新接口\n* at aspect\n\n**跑起来√** [springidol-aop](https://github.com/vonzhou/SpringInAction3/tree/master/springidol-aop)\n\n**跑起来√** [springidol-aspectj](https://github.com/vonzhou/SpringInAction3/tree/master/springidol-aspectj)\n\n## 5. 征服数据库\n\n* Spring在数据访问层使用模板方法设计模式，模板template管理数据访问过程中固定的部分，回调callback处理自定义的数据访问细节\n* 想要控制的越多就越复杂，更多的冗余逻辑，tradeoff\n* 使用MySQL数据库\n* 体会各种持久化方法的使用\n\n**跑起来√** [spitter-persistence-jdbc-conventional](https://github.com/vonzhou/SpringInAction3/tree/master/spitter-persistence-jdbc-conventional)\n\n**跑起来√** [spitter-persistence-jdbc-template](https://github.com/vonzhou/SpringInAction3/tree/master/spitter-persistence-jdbc-template)\n\n**跑起来√** [spitter-persistence-hibernate-contextual-session](https://github.com/vonzhou/SpringInAction3/tree/master/spitter-persistence-hibernate-contextual-session)\n\n**跑起来√** [spitter-persistence-jpa](https://github.com/vonzhou/SpringInAction3/tree/master/spitter-persistence-jpa)\n\n## 6. 事务管理\n\n* 事务的ACID特性\n* 编码式 vs 声明式事务在细粒度和易用性之间的权衡\n* Spring为每种场景定义了事务管理器（TransactionManager），底层是特定的事务实现\n* 要理解JDBC事务，Hibernate事务幕后的实现\n* 声明式事务的5个属性：传播行为，隔离级别，只读，超时，回滚规则\n\n**跑起来√** [spitter-service-declarative-tx](https://github.com/vonzhou/SpringInAction3/tree/master/spitter-service-declarative-tx)\n\n**跑起来√** [spitter-service-programmatic-tx](https://github.com/vonzhou/SpringInAction3/tree/master/spitter-service-programmatic-tx)\n\n## 7. 使用Spring MVC构建Web应用程序\n\n一个问题的记录，如下，解决方法把Spitter配置文件中的lazy设置为false，还有待好好理解，[参考](http://stackoverflow.com/questions/345705/hibernate-lazyinitializationexception-could-not-initialize-proxy)。\n\n```java\norg.hibernate.LazyInitializationException: could not initialize proxy - no Session\n\torg.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:148)\n\torg.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:266)\n\torg.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68)\n\tcom.vonzhou.spitter.persistence.Spitter_$$_jvst34e_0.getUsername(Spitter_$$_jvst34e_0.java)\n\tsun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\tsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tjava.lang.reflect.Method.invoke(Method.java:497)\n\tjavax.el.BeanELResolver.getValue(BeanELResolver.java:97)\n\torg.apache.jasper.el.JasperELResolver.getValue(JasperELResolver.java:110)\n\torg.apache.el.parser.AstValue.getValue(AstValue.java:169)\n\torg.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:184)\n\torg.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:943)\n\tohrg.apache.jsp.WEB_002dINF.views.home_jsp._jspx_meth_s_005fparam_005f0(home_jsp.java:317)\n\torg.apache.jsp.WEB_002dINF.views.home_jsp._jspx_meth_s_005furl_005f0(home_jsp.java:283)\n\torg.apache.jsp.WEB_002dINF.views.home_jsp._jspx_meth_c_005fforEach_005f0(home_jsp.java:208)\n\torg.apache.jsp.WEB_002dINF.views.home_jsp._jspService(home_jsp.java:155)\n\torg.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)\n\tjavax.servlet.http.HttpServlet.service(HttpServlet.java:729)\n\torg.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:438)\n\torg.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396)\n\torg.apache.jasper.servlet.JspServlet.service(JspServlet.java:340)\n\tjavax.servlet.http.HttpServlet.service(HttpServlet.java:729)\n\torg.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)\n\torg.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:168)\n\torg.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303)\n\torg.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1243)\n\torg.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1027)\n\torg.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:971)\n\torg.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)\n\torg.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)\n\torg.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:859)\n\tjavax.servlet.http.HttpServlet.service(HttpServlet.java:622)\n\torg.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)\n\tjavax.servlet.http.HttpServlet.service(HttpServlet.java:729)\n\torg.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)\n```\n\n\n表单验证效果：\n\n![](form-valid.jpg)\n\n一个问题的记录，如下， 根据日志输出大概可以看出在equals，hashCode方法的地方，所以要正确的override， 可以使用Commons lang。\n\n```java\njavax.validation.ValidationException: HV000041: Call to TraversableResolver.isReachable() threw an exception.\n\torg.hibernate.validator.internal.engine.ValidatorImpl.isReachable(ValidatorImpl.java:1531)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:1507)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:584)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:555)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:490)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:454)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:406)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:204)\n\torg.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:108)\n\torg.springframework.validation.DataBinder.validate(DataBinder.java:866)\n\torg.springframework.web.method.annotation.ModelAttributeMethodProcessor.validateIfApplicable(ModelAttributeMethodProcessor.java:164)\n\torg.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:111)\n\torg.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:99)\n\torg.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)\n\torg.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)\n\torg.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)\n\torg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)\n\torg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)\n\torg.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)\n\torg.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)\n\torg.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)\n\torg.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)\n\torg.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:870)\n\tjavax.servlet.http.HttpServlet.service(HttpServlet.java:648)\n\torg.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)\n\tjavax.servlet.http.HttpServlet.service(HttpServlet.java:729)\n\torg.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)\nroot cause\n\njava.lang.NullPointerException\n\tcom.vonzhou.spitter.persistence.Spitter.equals(Spitter.java:100)\n\torg.hibernate.validator.internal.engine.resolver.CachingTraversableResolverForSingleValidation$TraversableHolder.equals(CachingTraversableResolverForSingleValidation.java:127)\n\tjava.util.HashMap.getNode(HashMap.java:571)\n\tjava.util.HashMap.get(HashMap.java:556)\n\torg.hibernate.validator.internal.engine.resolver.CachingTraversableResolverForSingleValidation.isReachable(CachingTraversableResolverForSingleValidation.java:34)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.isReachable(ValidatorImpl.java:1522)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:1507)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:584)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:555)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:490)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:454)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:406)\n\torg.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:204)\n\torg.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:108)\n\torg.springframework.validation.DataBinder.validate(DataBinder.java:866)\n\torg.springframework.web.method.annotation.ModelAttributeMethodProcessor.validateIfApplicable(ModelAttributeMethodProcessor.java:164)\n\torg.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:111)\n\torg.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:99)\n\torg.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)\n\torg.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)\n\torg.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)\n\torg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)\n\torg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)\n\torg.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)\n\torg.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)\n\torg.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)\n\torg.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)\n\torg.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:870)\n\tjavax.servlet.http.HttpServlet.service(HttpServlet.java:648)\n\torg.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)\n\tjavax.servlet.http.HttpServlet.service(HttpServlet.java:729)\n\torg.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)\n```\n\n一个问题的记录，如下，**要加入依赖commons fileupload**(为何？？), 然后配置文件加入multipartResolver bean.\n\n```java\norg.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?\n\torg.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:980)\n\torg.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:870)\n\tjavax.servlet.http.HttpServlet.service(HttpServlet.java:648)\n\torg.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)\n\tjavax.servlet.http.HttpServlet.service(HttpServlet.java:729)\n\torg.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)\n```\n\n一个问题的记录，部署错误，折腾了如何在intellij中配置日志路径，但是没有看到日志在哪儿。采用另一个方法，把项目手动放到tomcat的webapps下面，然后run，出错后，会在其logs下面生成日志，然后去阅读，然后我通过阅读日志发现出的错误和数据库相关，才意识到MySQL么有启动。\n\n![](deploy-error.jpg)\n\n**参阅学习：**\n\nhttp://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/\n\n[Apache Tiles](http://tiles.apache.org/)\n\n[Chapter 15. Criteria Queries](https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querycriteria.html)\n\n[application/x-www-form-urlencoded or multipart/form-data?](http://stackoverflow.com/questions/4007969/application-x-www-form-urlencoded-or-multipart-form-data)\n\n了解 HSL 语法\n\n[Commons IO](http://commons.apache.org/proper/commons-io/)\n\n[What issues should be considered when overriding equals and hashCode in Java?](http://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java)\n\n**跑起来√**[spitter-web](https://github.com/vonzhou/SpringInAction3/tree/master/spitter-web)\n\n## 8. Spring Web Flow使用\n\n\n\n错误如下，关键在于var要在input之前，input之后就开始各种状态了。\n\n```java\norg.xml.sax.SAXParseException; lineNumber: 8; columnNumber: 96; cvc-complex-type.2.4.a: 发现了以元素 'var' 开头的无效内容。应以 '{\"http://www.springframework.org/schema/webflow\":input, \"http://www.springframework.org/schema/webflow\":on-start, \"http://www.springframework.org/schema/webflow\":action-state, \"http://www.springframework.org/schema/webflow\":view-state, \"http://www.springframework.org/schema/webflow\":decision-state, \"http://www.springframework.org/schema/webflow\":subflow-state, \"http://www.springframework.org/schema/webflow\":end-state, \"http://www.springframework.org/schema/webflow\":global-transitions, \"http://www.springframework.org/schema/webflow\":on-end, \"http://www.springframework.org/schema/webflow\":output, \"http://www.springframework.org/schema/webflow\":exception-handler, \"http://www.springframework.org/schema/webflow\":bean-import}' 之一开头。\n\tcom.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)\n\tcom.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)\n\tcom.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:396)\n\tcom.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:327)\n\tcom.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:284)\n\tcom.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:452)\n```\n\n\n\n\n**参阅学习：**\n\n* [Spring Web Flow官网](http://projects.spring.io/spring-webflow/)\n* [spring-webflow-samples](https://github.com/spring-projects/spring-webflow-samples)\n* [Spring Web Flow 2.0 入门](http://www.ibm.com/developerworks/cn/education/java/j-spring-webflow/index.html)， 代码[CartApp](https://github.com/vonzhou/SpringInAction3/tree/master/CartApp)\n* [What's the difference between @Component, @Repository \u0026 @Service annotations in Spring?](http://stackoverflow.com/questions/6827752/whats-the-difference-between-component-repository-service-annotations-in)\n* JSPX 和 JSP 的区别\n\n**跑起来√**  [Spizza](https://github.com/vonzhou/SpringInAction3/tree/master/SpringPizza)\n\n## 9. 保护Spring应用\n\n\n* 登录表单的提交action的url要和security配置中form-login的login-processing-url对应起来，否则谁知道怎么处理\n* 关于CSRF的一点总结，首先要在form里面配置一个csrf的隐藏域因为Spring默认开启了csrf防护，否则Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'. \n* 注意login表单中的用户名和密码input的name不能是默认的j\\_username, 发生了Invalid CSRF Token的问题，我不知道为何。书中的代码怎么通过的？我在这里迷失了很久！解决的方法就是在security配置中的form-login中显示的指定username-parameter=\"username\", password-parameter=\"password\". login.jsp中保持和这里的一致。\n* **书中对该框架的讲解只是抛砖引玉，需要自己深入学习**\n\n一个问题的记录，当security配置文件中配置两个access ROLE的时候就会出现重定向次数太多的错误，对应这种场景必定有解决方法，这里先配置一种ROLE。\n\n![](too-many-redirects.jpg)\n\n**参阅学习：**\n\n* [spring-security/samples](https://github.com/spring-projects/spring-security/tree/master/samples)\n* [ Cross Site Request Forgery (CSRF)](http://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html)\n* [New in Spring MVC 3.1: CSRF Protection using RequestDataValueProcessor](http://blog.eyallupu.com/2012/04/csrf-defense-in-spring-mvc-31.html)\n* \n\n\n**跑起来√** [spitter-web-security](spitter-web-security)\n\n\n\n## 10. 使用远程服务\n\n* 先要保证不用Spring的时候这些RPC的基本使用和原理，否则框架会蒙蔽你的脑子\n* 在阅读Oracle的rmi文档的时候，感觉很爽啊，有时间多看看这些原汁原味的文档，收获自然不菲\n* java -cp 参数的多个路径用冒号分隔，. 代码当前目录\n* 实现一个简单的RMI示例，Java RMI tutorial没有跑通。如果出现LocateRegistry.createRegistry()绑定默认的1099端口失败，那么就先杀死他，然后启动rmiregistry，如下：\n\n![](rmidemo/kill-rmiregistry.jpg)\n\n* 简单示例GreetingService中, 通过rmi 方法调用返回的是String对象,String显然实现了java.io.java.io.Serializable，在这里问题UnmarshalException-\u003eNotSerializableException就出现在远程方法调用返回的是Spitter对象,所以就要牵扯到对象从RMI server传输到本地,所以Spitter要实现Serializable\n* 根据出现的 UnmarshalException 的 ClassNotFoundException 的类的包名，还可以发现一个问题， Spitter对象是在远程获得的，所以需要load到本地，所以包名也要一致，否则就属于不同的Spitter啊。\n* 纯粹的使用Hessian, 然后整合到Spring中 [示例 hello-hessian-spring](hello-hessian-spring) 。Spring 并没有做更多的简化，只是集成。\n\n\n\n\n**参阅学习：**\n\n* [Trail: RMI: Table of Contents](http://docs.oracle.com/javase/tutorial/rmi/TOC.html),  搞了半天没有跑通，草! \n* [stackoverflow - hibernate exception Null value was assigned to a property of primitive type setter](http://stackoverflow.com/questions/3154582/why-do-i-get-a-null-value-was-assigned-to-a-property-of-primitive-type-setter-o)\n* [stackoverflow - WriteAbortedException: writing aborted; java.io.NotSerializableException:](http://stackoverflow.com/questions/2294551/java-io-writeabortedexception-writing-aborted-java-io-notserializableexception)\n\n\n**跑起来√** [spitter-remoting-rmi](spitter-remoting-rmi)\n\n**跑起来√** [hello-hessian](hello-hessian) 整合到Spring中, [hello-hessian-spring](hello-hessian-spring), [hello-hessian-spring-client](hello-hessian-spring-client)。\n\n**跑起来√** [hello-httpinvoker](hello-httpinvoker)\n\n\n## 11. 为Spring添加REST功能\n\n* 理解REST的基本哲学\n* 处理RESTful的URL，写对应的控制器\n* HTTP各种方法的理解\n* 使用RestTemplate\n* 编写REST客户端，以及HttpMessageConverter对客户端的适应\n* component-scan中的多个package使用逗号分隔\n* Fuck, 以后尽量手动的mvn clean pakcage， 然后用IDE部署运行，否则有些问题。\n\n**跑起来√** [spitter-web-rest]()\n\n\n## 12. Spring消息\n\n* 之前在阿里实习的时候，对RocketMQ有过较为深入的阅读\n* ActiveMQ的使用，先要下载，启动broker，作为消息生产者消费者之间的代理\n\n![](activemq-start.jpg)\n\n* This class is not trusted to be serialized as ObjectMessage payload.  使用ObjectMessage的时候需要设置信任的package\n\n```java\nCaused by: java.lang.ClassNotFoundException: Forbidden class org.springframework.remoting.support.RemoteInvocation! This class is not trusted to be serialized as ObjectMessage payload. Please take a look at http://activemq.apache.org/objectmessage.html for more information on how to configure trusted classes.\n\tat org.apache.activemq.util.ClassLoadingAwareObjectInputStream.checkSecurity(ClassLoadingAwareObjectInputStream.java:112)\n\tat org.apache.activemq.util.ClassLoadingAwareObjectInputStream.resolveClass(ClassLoadingAwareObjectInputStream.java:57)\n\tat java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613)\n\tat java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)\n\tat java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)\n\tat java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)\n\tat java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)\n\tat org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:206)\n\t... 14 more\n```\n\n简单起见设置为：\n\n```java\nSystem.setProperty(\"org.apache.activemq.SERIALIZABLE_PACKAGES\",\"*\");\n```\n \n\n**参阅学习：**\n\n[ActiveMQ ObjectMessage](http://activemq.apache.org/objectmessage.html)\n\n**跑起来√** [messaging](messaging)\n\n\n## 13. 将Spring Bean导出为MBean\n\n* 前提是理解JMX，看文档\n\n## 14. 其他Spring技巧\n\n* 将一些需要修改的配置细节外部化一个单独的配置文件，系统文件，或环境变量中\n* JavaMailSender\n* 调度任务 \n\n\n## 迷失\n\n![](lost.jpg)\n\n\n\u003e Spring旅程才刚刚开始！\n\u003e \n\u003e vonzhou 2016.4.26 \n\n\n\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvonzhou%2Fspringinaction3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvonzhou%2Fspringinaction3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvonzhou%2Fspringinaction3/lists"}