Skip to content

Instantly share code, notes, and snippets.

@swachian
Last active December 20, 2015 04:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save swachian/6070011 to your computer and use it in GitHub Desktop.
Save swachian/6070011 to your computer and use it in GitHub Desktop.
Spring3 的学习及同Rails的对比
// Source project: sip01, branch: 04 (Maven Project)
package com.springinpractice.ch01;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.springinpractice.ch01.model.Account;
import com.springinpractice.ch01.service.AccountService;
public class ConsoleApp {
public static void main(String[] args) throws Exception {
ApplicationContext appCtx =
new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService =
(AccountService)appCtx.getBean("accountService");
List<Account> delinquentAccounts = accountService
.findDeliquentAccounts();
for (Account a : delinquentAccounts) {
System.out.println(a.getAccountNo());
}
}
}

用SSH进行开发已经五六年了,这个架构这些年一直没动过。随着Spring的日益兴盛,而Struts2相对停滞沉闷且安全漏洞始终没有很好地解决。 因此决定全面转换到Spring,即采用Spring MVC。下面是一些自己的体会。

总体感觉

Spring引以为豪的是依赖注入,其目的是方便组装,更现实的意义应该是方便测试。放在main或者test文件里,就可以调用。这一点确实对 web开发很重要,避免了对容器的过度依赖。

而它的MVC凑合着也能用用。比起Struts2几乎已经不分伯仲了,比Rails那就差的远了。

静态资源

静态资源的处理是最大的进入。终于全部放到某个目录下了,这样偏于集中管理和存放规范。配置也比较简单。

控制器

MVC中的C,由Mapping选择和交付处理两个模块组成。Mapping基本不需要写什么xml的内容了,改成了在controller的class文件里写annotation。@RequestMapping, @Controller 虽然还是有点啰嗦,还是可以接受的。引入Restful可以说是一大进步,Java的框架页终于开始支持 PathParameter 。这些都是明显受到了Rails的影响,而且也学的相当到位。

  @Autowired
	HttpServletRequest request = null;
	
	@Autowired
    HttpSession session = null;

这样写,request和session就可以被注入了,甚至连setter的方法也不用设置,应该是直接类型注入的。查了一下@Autowired也确实优先按类的类型注入。

参数填写

尤其是依靠 依赖注入 在设置参数、设置request等方面有着突出的表现。较之struts2的 user.name式命名方式, name直接赋值给User类型的参数是更合理些的。这方面做得真的很棒。

参数验证

这个就比较差了。写在model里的annotation会一场臃肿,表现力远远还不如直接写java。

C和V之间的信息传递

Controller和View之间传递主要包含两个部分,一个是渲染的view的类型,另一个就是controller里面参数的数据。这部分也已经做的很不错了。model.addAttribution() return "sss/home 都已经很简洁。对HTML和JSON的支持也都不错。

视图

视图的代码

视图层方面又多了很多标签。个人不喜欢标签,标签就是code,表达力还不如java的code制造方式。每个框架还企图再造一套标签,这有什么用的意义呢?

布局

视图方面是用的tiles,伴随着struts1出来的东西了,凑合着也能用用,比Rails是差远了。

分页

这个可能不单单是视图层面的问题,而是属于整个栈的。没有特别简单的整合办法。

JpaRepositories, PageRepositories都支持分页和排序了,再加一个绘制的标签或helper,基本也相当凑合了可以。

模型

之前认为spring没有自己的模型。但仔细看下来,spring data jpa正是spring的模型层。借用hibernate做provider,可以提供相当优秀的存储层和Pojo模型。加之java spring擅长的事务处理,这部分已经很强悍了。

并且,居然还增加了对动态find方法的支持,进步相当明显。

Spring3已经具备了一个可以独立运作的MVC库,去除Struts2已经水到渠成。模型层和控制层已经很强了。当然,视图层还是比较弱的。 所以,对于没有视图的web应用,比如作为接口机或者配合json的应用,spring已经很不错。性能、事务方面java还是很强悍的。

第一章 DI(IOC)

如何通过外围的控制取代new的方式,带来更灵活的代码组织方式。核心内容在于spring的container,可以返回bean(对象)。

标注取代xml是趋势,当然还是要在xml里面声明一下auto的内容。

第二章 JPA

Spring 3的JPA真的太棒了,寻找多年的java版ActiveRecord终于出现了。

controller里直接支持pageable的写法

  <!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven>
		<argument-resolvers>
			<beans:bean class="org.springframework.data.web.PageableArgumentResolver" />
		</argument-resolvers>
	</annotation-driven>

http://localhost:8080/simmax/xs/setXs/?page.page=3&page.size=5 , spring会自动把page-1, 然后再new PageRequest(page-1, size)

第三章 MVC

  • handler

多handler的配法,通过order确定哪个mapping规则先期作用,annotation和硬写都是其中的一种handler。

<bean class="org.springframework.web.servlet.handler.
➥ SimpleUrlHandlerMapping"
p:order="0">
<property name="mappings">
<props>
<prop key="/index.html">coreController</prop>
<prop key="/about.html">coreController</prop>
<prop key="/contact/*">contactController</prop>
<prop key="/forums/*">forumsController</prop>
</props>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.support.
➥ ControllerClassNameHandlerMapping"
p:order="1"/>
  • HANDLERINTERCEPTORS
<bean id="webContentInterceptor"
class="org.springframework.web.servlet.mvc.WebContentInterceptor">
<property name="supportedMethods">
<list>
<value>GET</value>
<value>POST</value>
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.support.
➥ ControllerClassNameHandlerMapping">
<property name="interceptors">
<list>
<ref bean="webContentInterceptor"/>
</list>
</property>
</bean>
  • ViewResolver
<bean class="org.springframework.web.servlet.view.
➥ InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp"/>

redirect: and forward:

  • argumentResolver 可以给controller加入需要的参数,实质上是前置了handlerinterceptor
<annotation-driven>
<argument-resolvers>
<beans:bean class="org.springframework.mobile.device.
➥ DeviceWebArgumentResolver" />
<beans:bean class="org.springframework.mobile.device.site.
➥ SitePreferenceWebArgumentResolver" />
</argument-resolvers>
</annotation-driven>
You configure two different

第四章 初级例子

@Controller
@RequestMapping("/users")
public class AccountController {
private static final Logger log =
LoggerFactory.getLogger(AccountController.class);
@RequestMapping(value = "new", method = RequestMethod.GET)  // new前面加/可以重载整个类的前缀/users
public String getRegistrationForm(Model model) {
model.addAttribute("account", new AccountForm());
return "users/registrationForm";
}
@RequestMapping(value = "", method = RequestMethod.POST)
public String postRegistrationForm(AccountForm form) {
log.info("Created registration: {}", form);
return "redirect:registration_ok";
}
}
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head><title>New User Registration</title></head>
<body>
<form:form action="." modelAttribute="account">
<h1>New User Registration</h1>
<div>Username: <form:input path="username" /></div>
<div>Password: <form:password path="password" /></div>
<div>Confirm password: <form:password path="confirmPassword" /></div>
<div>E-mail address: <form:input path="email" /></div>
<div>First name: <form:input path="firstName" /></div>
<div>Last name: <form:input path="lastName" /></div>
<div><form:checkbox id="marketingOk" path="marketingOk" />
Please send me product updates by e-mail.</div>
<div><form:checkbox id="acceptTerms" path="acceptTerms" />
I accept the <a href="#">terms of use</a>.</div>
<div><input type="submit" value="Register" /></div>
</form:form>
</body>
</html>

Java config vs XML config

说句实话,更喜欢Java config。无他,这样更灵活,也不啰嗦。

@Configuration
@EnableJpaRepositories("hello")
@EnableTransactionManagement(proxyTargetClass = false)
@ComponentScan("hello")
public class ApplicationService {

  @Bean
	public DataSource dataSourceMy() {
		//http://fruzenshtein.com/spring-jpa-data-hibernate-mysql/
		DriverManagerDataSource dataSource = new DriverManagerDataSource();

		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUrl("jdbc:mysql://192.168.137.102:3306/hibnatedb");
		dataSource.setUsername("test");
		dataSource.setPassword("test123");

		return dataSource;
	}

	@Bean
	public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
		return new JpaTransactionManager(emf);
	}

	@Bean
	public JpaVendorAdapter jpaVendorAdapter() {
		HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
		jpaVendorAdapter.setDatabase(Database.MYSQL);
		jpaVendorAdapter.setGenerateDdl(true);
		jpaVendorAdapter.setShowSql(true);
		return jpaVendorAdapter;
	}


	@Bean
	public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
		LocalContainerEntityManagerFactoryBean lemfb = new LocalContainerEntityManagerFactoryBean();
		lemfb.setDataSource(dataSourceMy());
		lemfb.setJpaVendorAdapter(jpaVendorAdapter());
		//lemfb.setPackagesToScan("repositories");
		lemfb.setPackagesToScan("hello");
		return lemfb;
	}
}

上面这些就可以定义完一组service中带transaction的config,且jpa也启动了事务。

另外,java config里面可以自由引入xml,但是xml却无法引入java config。

Transactional

Propagation 控制的是有无事务。默认是Required,大部分场景够用。其含义是如果有事务则新的操作纳入该事务中,如果还没有事务,则新生成一个事务。

但是,是否回滚,则由其他参数rollback-for确定,默认情况下只对RuintimeException例外进行回滚。下面的Throwable.class才会让exception回滚。

@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = { Throwable.class })
看到楼上很多在喷互联网,说是在烧风投的钱,不得不来反驳一下:
1,首先纠正一下楼主,互联网行业不是5%的top都能拿60万,毕竟技术岗位太多了,你看到的也许是清华计算机系5%,即使如此,也未必能达到5%,大部分互联网岗位还是20万左右。
2,互联网为什么钱多,两个原因,第一,暴利,游戏、媒体、广告,这都是实实在在来钱的,而且是利润率极高的,楼主说的这些大公司,根本不存在烧风投钱的问题,去看看百度、腾讯的财报,就知道了,连续多年的高增长率和利润率;第二,互联网为什么发钱,因为这个行业,不需要(或者相比传统行业很少)其它成本,最大的成本是人,谁拥有最好的程序员、开发者,谁才有能力做出好的产品。
3,互联网起薪平均确实秒杀金融,但是绝大多数人30万以后 很难再涨吧,成长性应该是低于金融,举个简单的例子,各大总行3年后到手20~30万的话,还是比大部分互联网强的,考虑到工作强度,那更是好的多。
4,国内互联网秒杀国外,那是国内市场问题,很多公司,他就只搞国内市场,反正有10亿潜在用户,够他玩一辈子了,facebook和google 全球客户加起来,还是比国内多吧。总体来说国内互联网企业的高端码农、产品、平台还是远远不如google ms fb amazon。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment