大家好,我是编程小6,很高兴遇见你,有问题可以及时留言哦。
课程目标:对Spring有一个基本的了解,可以使用Spring开始进行系统开发;
https://spring.io/
开始之前,我要告诉大家一个学习的方法论,WHY(为什么)-WHAT(是什么)-HOW(怎么用)。应该有同学知道摩尔定律,其实在计算机编程领域,知识的更新换代也是非常快的,我们只有掌握正确的学习方法论,知道技术更迭背后的原因,才能摆脱成为新技术学习的傀儡,我们需要知其然,更要知其所以然,可能最后我们就不是跟风,而是引领甚至是创造技术革新。
要比较好的理解Spring框架,我们需要追溯一下历史,厘清背后的原因,同时也可以窥探一些技术更迭的本质。
Java技术分为javase、javame、javaee三个部分。
Javaee指企业级开发,它的核心技术更迭从EJB1 到 EJB2 再到 EJB3,其中EJB3已经参考了Spring框架的大量思想,并且是java官方出品,但Spring在很多方面表现的更加优秀,特别是基于POJO的特性,使得它非常易用,所以很快流行起来,并且成为直到现在java企业级开发的首选框架(如果有对Spring前世今生,以及最开始Spring想要解决的问题以及解决思路更深入研究的话,可以看看《j2ee without EJB》这本书 https://item.jd.com/10029953147704.html)
在当时那个年代,EJB是一个非常重,侵入性很强的技术,想要把它run起来非常难,以至于当年有个玩笑:如果能把EJB程序run起来已经是个大牛了,从这里大家应该基本可以推断出Spring是为简化企业级java应用开发而生的。
因为是入门篇,我们点到为止,感兴趣的同学可以自行查阅或先把兴趣点记录下来,在后续的进阶篇和精通篇跟着老师一起探索。
https://spring.io/ Spring makes java simple、modern、productive、reactive、cloud-ready。
Spring makes programming Java quicker, easier, and safer for everybody.
最开始大家只需要对Spring有一个大概的概念,入门篇主要以快速上手为目的。
java编程
public class Son{
private String prop1;
private String prop2;
//构造函数
//setter、getter for prop1 prop2
public void do(){
//biz code
}
}
public class Parent{
private Son son1;
private Son son2;
//构造函数
//setter、getter for son1 son2
//其他的业务方法
public void doSomeThing(){
son1.do();
son2.do();
}
}
public class Biz{
public static void main(String[] args){
Son son1 = new Son("prop1", "prop2");
Son son1 = new Son("prop1", "prop2");
Parent parent = new Parent(son1, son2);
parent.doSomeThing();
}
}
javaweb编程
//必须实现service()方法
public void service(ServletRequest servletRequest,ServletResponse servletResponse){
HttpServletRequest request;
HttpServletResponse response;
try{
request=(HttpServletRequest)servletRequest;
response=(HttpServletResponse)servletResponse;
}catch(ClassCastException){
throw new ServletException("non-http request or response");
}
//调用service()方法
this.service(request,response);
}
<!-- 必须要进行对应的配置,才能保证该servlet生效 -->
<web-app>
<servlet>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>
</web-app>
java编程
Class Parent{
@Autowired
private Son son1;
@Autowired
private Son son2;
//构造函数
//setter、getter for son1 son2
//其他的业务方法
public void doSomeThing(){
son1.do();
son2.do();
}
}
javaweb编程
@Controller
public class HelloWorldController{
@GetMapping("/")
public String helloWorld(){
return "helloworld";
}
}
通过上一节的比较,我们发现引入Spring以后,会让我们的编码工作非常的高效和简单,其实这只是冰山一角,随着Spring技能的逐步掌握,我们可以更好的理解 ”Spring makes java simple、modern、productive、reactive、cloud-ready“
Spring的核心是提供了一个容器(container),通常成为Spring 应用上下文(Spring application context),它会创建和管理应用组件(bean),这些组件会在Spring上下文中装配在一起形成我们完整的应用程序。
组件装配有两种方式:xml 和 java代码
xml:
<bean id="aService" class="com.***.Aservice" />
<bean id="bService" class="com.***.Aservice">
<constructor-arg ref=aService" />
</bean>
java注解:
@Configuration
public class ServiceConfiguration {
@Bean
public AService aService(){
return new AService();
}
@Bean
public BService bService(){
return new BService(aService());
}
}
自动配置(autoconfiguration)=自动装配(autowiring)+配置扫描(component scanning)+其他,即所谓的springboot。
xml配置方式基本已经过时,所以在我的概念里spring和springboot认为是一回事,都使用Springboot方式来做Spring应用开发。
IoC是一种通过描述来生成或者获取对象的技术,而这个技术不是Spring甚至不是Java独有的。对于Java初学者更多的时候所熟悉的是使用new关键字来创建对象,而在Spring中则不是,它是通过描述来创建对象。只是Spring Boot并不建议使用XML,而是通过注解的描述生成对象;
AOP面向切面的编程,大家的第一反应AOP和OOP是不是同一个层次的东西,基本可以这么理解。OOP在代码的封装、重用等方面有很大的作用,但在有些情况下,面对重复的代码却无能为力。拿java的JDBC编程来举例:
Connection connection = null;
try {
// 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取连接
String url = "jdbc:mysql://127.0.0.1:3306/test";
String user = "user";
String password = "pwd";
connection = DriverManager.getConnection(url, user, password);
//非自动提交事务
connection.setAutoCommit(false);
// 数据库操作
userDao.insertUser(connection, user);
//提交事务
connection.commit();
} catch(Exception exception){
try {
//事务回滚
connection.rollback();
} catch(SQLException sqlException) {
//log error
}
}finally {
// 关闭连接,释放资源
try {
if (connection != null) {
connection.close();
}
} catch(SQLException sqlException) {
//double close
//log error
}
}
是不是存在大量的重复代码,在这种情况下,AOP就可以很好的解决这个问题。
@Autowired
private UserDao userDao;
@Transactional
public int insertUser(User user){
userDao.insertUser(user);
}
和上面的代码的作用一致,这就完全有赖于Spring AOP的强大能力。它的实现主要是动态代理技术以及默认实现(约定优于配置的思想)
业界比较流行的还有CGLIB、Javassist、ASM等。Spring采用了JDK和CGLIB,对于JDK而言,它是要求被代理的目标对象必须拥有接口,而对于CGLIB则不做要求。
在springboot方式的spring开发中,直接使用springMVC的可能性越来越小,从spring网站就可以印证这一点,非常艰难的可以找到一小段它的指南:https://spring.io/guides/gs/serving-web-content/
在传统web开发的年代,MVC的架构是非常流行的,后端工程师高频使用springMVC,我们做一个简单了解。
web开发经历的几个阶段:
SpringMVC的处理流程:
SpingMVC是Spring家族的一部分,和Spring深度集成;支持各种视图不局限于JSP;清晰的角色分配【前端控制器(dispatcherServlet) , 请求到处理器映射(handlerMapping), 处理器适配器(HandlerAdapter), 视图解析器(ViewResolver)】,编码简单;
MVC的架构有一个硬伤,就是视图层的处理,虽然已经做了足够多的解耦,但从开发角度看,特别是系统运行时(开发联调、部署等)还需要视图(前端)开发工程师依赖后端工程师,就会导致开发过程不畅产生阻塞,加之移动互联网大行其道,前端技术的发展也进入快车道,前后端分离越来越流行,后端工程师就更多的关注在业务逻辑层面的设计和编写上,SpingMVC就慢慢变成支撑RESTful Web Service的幕后英雄。
前后端分离以后,前端和后端的交互通过http协议,报文一般都采用json格式,可以理解为面向http API的编程,关于RESTful,大家可以自行延伸阅读,因为浏览器的限制,我们并没有严格按照RESTful风格编程。
我们随便打开一个网站(https://www.infoq.cn/),就可以看到使用ajax调用http api,如下图:
那服务端怎么实现呢,上代码:
model代码:
@Data
public class Nav {
private int code;
private Map<String, Object> data;
private Map<String, Object> error;
private Map<String, Object> extra;
}
controller代码:
@GetMapping("/getNav")
public Nav getNav(){
Nav nav = new Nav();
nav.setCode(9999);
Map<String, Object> data = new HashMap<>();
data.put("obt", "val");
nav.setData(data);
return nav;
}
效果:
工欲善其事必先利其器,我们使用IDEA和spring initializr初始化spring工程。
一切都非常简单,但已经具备了足够多的能力,这都有赖于Spring的强大。
我们参见spring官方网站。
我们用到的就是Spring Boot、Spring框架、Spring Security、Spring Initializr,其他暂时用不到或一直用不到,后面我们会引入Spring Cloud Alibaba。