浅谈java-web开发技术栈

10 篇文章 1 订阅
4 篇文章 0 订阅

1. 前言

1.1 java-web说明

1.2 java-web前后端分离

1.3 java-web的开发生命周期

2. 技术栈

2.1 前端技术栈

2.1.1 HTML + CSS 实现静态页面

2.1.2 JavaScript动态渲染页面

2.1.3 Vue + Element/Iview 急速前端页面开发

2.2 后端技术栈

2.2.1 Spring框架

2.2.2 SpringMVC框架

2.2.3 Mybatis/JPA框架

2.2.4 SpringBoot框架

1. 前言

1.1 java-web说明

web的概念摘自百度百科,阐述如下:

World Wide Web,简称web,意思是:全球广域网,我们也称之为万维网。它是一种基于超文本和HTTP的、全球性的、动态交互的、跨平台的分布式图形信息系统。

简单来说,web就是一个网站。通过在浏览器地址栏输入指向该网站的URL,我们可以从该网站获取或上传相关的资源。如:淘宝/京东/知乎/微博等等的官网都可以认为是一个网站。
java-web项目,就是以主体编程语言是java,利用其他各种编程语言实现的辅助中间件,实现的网站项目。

1.2 java-web前后端分离

前后端分离已经是互联网项目开发的业界标准使用方式。
其核心思想是:前端HTML页面通过AJAX调用后端的Restful API接口,并统一使用JSON格式进行数据的交互。
把一个web项目切分成前端项目和后端项目的好处:

  • 术业有专攻。

后端java工程师对服务的追求是:高并发、高可用、高性能

这样后端java工程师就可以把更多的精力放在学习java基础,设计模式,jvm原理,spring+springmvc原理及源码,linux,mysql事务隔离与锁机制,http/tcp,多线程,分布式架构,弹性计算架构,微服务架构,java性能优化等等方面。

前端工程师对服务的追求是:页面表现,速度流畅,兼容性

这样前端工程师就可以把更多的精力放在学习html5,css3,jquery,angularjs,bootstrap,reactjs,vuejs,webpack,less/sass,gulp,nodejs,Google V8引擎,javascript多线程,模块化,面向切面编程,设计模式,浏览器兼容性,性能优化等等方面。

  • 耦合低,职权明确,开发速度快。

在开需求会议时,由前端工程师和后端工程师商议并统计要实现的接口。需要按照统一的标准,将每个接口的请求参数、方法、路径以及返回值都确定下来,并汇总成最终的接口文档。

前端工程师只需要关注页面以及路由的实现,后端工程师只需要关注接口实现以及性能优化。两者可以基于接口文档并行开发。而且这种开发方式在后期测试以及上线后,更有利于问题的排查定位。

  • 可扩展性强。

前端服务器使用nginx,后端服务器使用tomcat。前端的css/js/图片等静态资源可以放在特定的文件服务器上(如阿里的oss服务器)并使用cdn加速。然后,除接口以外的所有http请求全部会转移到nginx上,能够极大地减少后端服务器的压力。后端服务也可以按数据库、缓存、消息队列、应用切割等方式进行拆分并发布到不同的服务器上,能够降低单个节点的服务器宕机造成的影响。

按我自己的理解,前后端分离之后,

  • 前端工程师主要负责的工作就是:静态页面及路由的实现,以事件驱动的动态页面渲染实现
  • 后端工程师主要负责的工作就是:合理切分业务并建库建表,相关接口、初始化任务、定时任务的实现

1.3 java-web的开发生命周期

我理解的web开发迭代流程图如下:

1-web开发流程图
java-web开发生命周期详解如下:

  • 由产品经理与客户进行沟通,确定客户需要实现的功能并撰写相关的需求文档;
  • 基于需求文档,UI设计师与产品经理沟通协商后,UI设计师会设计出相应的UI原型。产品经理会基于UI原型再次跟客户沟通,确定是否满足需求,待UI设计师完善后,确定最终的UI原型。
  • 项目经理基于UI原型,组织产品经理、UI设计师、前端工程师、后端工程师进行需求会议,确定接口文档的撰写规范。然后,由前端工程师和后端工程师协商撰写接口文档。
  • 前端工程师基于UI原型和接口文档进行页面以及路由的开发,同时后端工程师基于接口文档进行业务的切分建库建表,并进行相关接口、初始化任务、定时任务的实现。
  • 确定前后端功能均开发完善后,由测试工程师进行相关功能的测试。基于测试过程中出现的问题,前后端需要进行相关问题的修复解决,确保测试正常。
  • 测试通过后,由运维工程师发布上线新服务,并时刻监测优化服务的相关配置参数。

实际的开发过程可能不会这么规范,但java-web项目的开发迭代生命周期,基本都是按照这个流程进行的。

2. 技术栈

2.1 前端技术栈

2.1.1 HTML + CSS 实现静态页面

  • Hyper Text Mark-up Language,超文本标记语言,简写为HTML。
  • Cascading Style Sheet,层叠样式表,简写为CSS。
    htmlcss是网页的基础。
    html包含的是一系列统一规定的标准标签,用来定义网页的基础布局。如我们最常见的元素:块级元素<div>标签和行内元素<span>标签。
    css就是为了将页面内容与页面表现区分开来的,通过选中html中的某块内容来按某种要求显示。其中最重要的是要理解盒子模型选择器部分样式定义方法

简单用实际的案例说明如下:
新建一个文件1.html并编辑内容如下:

<html>
  <body>
    <div>
      我是块级元素div,我会独占一行
    </div>
    <span>
      -------我是行内元素span1,可与其他行内元素共同占用1行,长度自适应并会自动换行-------
    </span>
    <span id="test">
      -------我是行内元素span2,可与其他行内元素共同占用1行,长度自适应并会自动换行-------
    </span>
    <span>
      -------我是行内元素span3,可与其他行内元素共同占用1行,长度自适应并会自动换行-------
    </span>
  <style>
    #test {
      font-size: 18px;
      color: red;
    }
  </style>
  </body>
</html>

将该文件在浏览器中打开的效果如下:

2-html+css说明

如上图所示:

  • <div>是块级元素,其中的内容会独占一行。<span>是行内元素,多个行内元素会共占1行,并且其长度自适应并会自动换行。
  • 行内元素span2定义了属性id值为test,通过css的id选择器选中该元素并设置了字体大小为18px,字体颜色为红色。

2.1.2 JavaScript动态渲染页面

JavaScript是一门脚本编程语言。
这里简单谈一下我对JavaScript的理解。它在浏览器主要做的事情有:监听浏览器网页的各种事件,基于各种事件的回调发起http请求或者直接动态渲染DOM(html中的某个元素)。

简单用实际的案例说明如下:
新建一个文件2.html并编辑内容如下:

<html>
  	<body>
   		<button onClick="toRed()">变红</button>
   		<button onClick="toBlue()">变蓝</button>
   		<p id="test">未点击前的DOM</p>
  	</body>
	<script>
		function toRed() {
			document.getElementById('test').innerHTML = "<div style=\"color:red;\">点击了变红按钮</div>"
		}
		function toBlue() {
			document.getElementById('test').innerHTML = "<div style=\"color:blue;\">点击了变蓝按钮</div>"
		}
	</script>
</html>

将该文件在浏览器中打开的效果如下:

3-javascript事件回调操作dom

如上图所示:

  • 页面中有两个按钮<button>变红</button><button>变蓝</button>。这两个按钮分别绑定了两个不同的点击事件。
  • 变红按钮绑定的点击回调事件是toRed(),其处理内容是:通过全局文档对象document查找到id为testdom元素,并将其内部的html修改为“点击了变红按钮”。
  • 变蓝按钮绑定的点击回调事件是toBlue(),其处理内容是:通过全局文档对象document查找到id为testdom元素,并将其内部的html修改为“点击了变蓝按钮”。

使用javascript在浏览器/客户端编程(CS/BS中的Client/Browser端)时,我们能够监听用户操作触发的事件,基于预先定义好的事件回调处理,动态地修改页面的内容和样式。

javascript中最重要的一个技术点是AJAX。客户端可以使用AJAX技术向服务端发送HTTP请求。

相关的基础代码如下:

// 创建XMLHttpRequest对象
var request = new XMLHttpRequest();

// 当http请求的状态发生变化时,会调用onreadystatechange()方法
request.onreadystatechange = function(){
  // 当readyStatue = 4且status = 200时,表示http请求成功完成
  if (request.readyState === 4 && request.status === 200) {
    // 获取http请求返回的字符串类型的响应文本
    var response = request.responseText;
    // 通过json解析后,将响应文本的值填充到页面对应的元素中
    var jsonObj = JSON.parse(response);
    // todo 将响应文本解析之后的内容填充到页面中
  }  
}
// 规定http请求的的类型、路径、是否异步
request.open('method_type','url',async);
// 如果是post请求提交表单数据,需要设置请求头
request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// 发送http请求
request.send();

简单说明一下:
我们可以利用XMLHttpRequest对象实例发送HTTP请求。其中主要用到该实例的三个方法:open(),send()onreadystatechange()

  • open()用来指定发起HTTP请求的方法类型、路径和是否异步。
  • send()用来真正发送HTTP请求。
  • onreadystatechange(),当该HTTP请求的状态发生改变时,会回调该方法。我们可以利用该实例判断服务器是否正确处理该请求(状态码为200时),如果正确响应则可将返回值解析后填充到当前页面的某个标签中。

2.1.3 Vue + Element/Iview 急速前端页面开发

当前主流的三大前端开发框架是:React,Vue,Angular。其中最好入门的就是Vue框架。熟读一遍Vue官方文档,理解它的这种数据与页面双向绑定的概念,实际上手写几个前端小项目就可入门。
ElementIview是两个非常常用的UI组件库。在项目中引入相关依赖包后,可以直接使用相关组件快速进行前端页面的开发。
ElementUI的官方文档详见element中文官方文档
IviewUI的官方文档详见iview中文官方文档
简单使用ElementUI提供的组件,查看其常用组件的样式效果如下:

新建一个文件3.html并编辑内容如下:

<html>
  <head>
    <!-- import CSS -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  </head>
  <body>
    <div id="app">
      <el-input placeholder="Element输入框"></el-input>
      <el-divider>Element分割线</el-divider>
      <el-button type="primary" @click="visible = true">Element按钮</el-button>
      <el-dialog :visible.sync="visible" title="Element对话框">
        <p>对话框内部内容</p>
      </el-dialog>
    </div>
  </body>
  <!-- import Vue before Element -->
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <!-- import JavaScript -->
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: function() {
        return { visible: false }
      }
    })
  </script>
</html>

将该文件在浏览器中打开的效果如下:

4-element样式效果图

2.2 后端技术栈

2.2.1 Spring框架

基于百度百科查看可知:Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。

控制反转:Inversion of Control,简单来说就是把对象生命周期的管理交给Spring容器。诸如:数据库连接池对象、Redis连接池对象、RabitMQ连接池对象、Quartz定时任务调度对象等等,这些“大”对象的创建和销毁是一个很损耗资源的操作。我们可以通过XMLJavaConfig的方式把这些对象交给Spring容器管理。如果需要使用时,通过依赖注入(DI:Dependency Injection)的方式拿到这些对象的实例即可。这些对象的创建和回收都会有Spring容器帮我们处理。注:Spring容器管理的对象都是单例的。

下面以Spring容器加载quartz相关对象的实例做出说明:

  1. 首先在pom.xml文件中导入必要依赖如下:
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>4.3.7.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>4.3.7.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.3</version>
</dependency>
  1. 运行定义打印当前时间的工作类TimePrinterJob内容如下:
public class TimePrinterJob {
    private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");

    public void printTime() {
        System.out.println("测试spring-xml配置quartz定时任务 TimePrinterJob.printTime() " + sdf.format(new Date()));
    }
}
  1. 以XML方式使Spring容器管理quartz相关的实例bean,配置文件spring-quartz.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="timePrinterJob" class="com.netopstec.spring_quartz.TimePrinterJob"/>
    <bean id="printTimeJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="timePrinterJob"/>
        <property name="targetMethod" value="printTime"/>
    </bean>
    <bean id="printTimeTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="printTimeJobDetail"/>
        <property name="cronExpression" value="/3 * * * * ?"/>
    </bean>

    <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="printTimeTrigger"/>
            </list>
        </property>
    </bean>
</beans>
  1. 实例化ClassPathXmlApplicationContext即启动Spring容器,最终效果如下:
    5-spring-quartz配置

上述相关源码详见我的github
说明如下:
这里主要查看的是spring-quartz.xml的内容。很明显地能看到,Spring管理的quartz相关的实例,有三层包裹关系。

  • printTimeJobDetail指定了要交由quartz管理任务对应的方法即TimePrinterJob.printTime()
  • printTimeTrigger指定了该任务的触发器即执行时机为“每3秒执行一次”。
  • scheduler指定了要启用的触发器列表。
    此时,业务逻辑比较简单,我们还能够迅速地梳理这些业务对象实例的关联关系。当随着业务的拓展,业务之间的耦合关联关系越来越复杂,使用Spring容器帮我们管理这些业务对象实例就很有必要了。

面向切面:Aspect Orient Programming,简单来说,将正常的业务流程当作一个维度,要新增的功能与业务无关,所以放在另外一个维度(切面)里面进行处理实现。
如日志、全局异常处理等相关功能与业务功能无关,此时就需要用到面向切面编程。很明显地,面向切面编程的核心原理是动态代理。Java支持使用jdkcglib来实现动态代理,相关的内容这里就不再赘述。
这里就简单介绍一下面向切面编程的相关概念和一个SpringBoot简单切面编程案例

  • 切面:Aspect,整个额外功能的整体;
  • 切点:PointCut,要添加额外功能对应于正常业务流程所在维度的位置;
  • 连接点:JointPoint,通过连接点我们可以获取正常业务流程中的相关信息。
  • 通知:Adivce,有如下类型的通知:前置通知before、后置通知after,环绕通知around,异常通知AfterThrowing等等。

一个SpringBoot简单切面编程使用案例如下:

@Component
@Aspect
public class LogAspect {

    @Pointcut("execution(* com.netopstec.test.service.impl..*.*(..)")
    private void pointCut(){}

    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("调用业务方法之前,可以执行添加一些其他的功能");
        // 实际调用方法
        Object[] args = joinPoint.getArgs();
        Object proceed = joinPoint.proceed(args);
        System.out.println("调用业务方法之后,可以执行添加一些其他的功能");
        return proceed;
    }
}

上面这个小案例,介绍的是功能最强大的通知—环绕通知。它是扫描com.netopstec.test.service.impl下的所有业务方法,在系统执行业务方法joinPoint.proceed(args)的前后,添加自定义额外功能(这里只是在控制台打印两句话,可以根据实际情况添加一些自己想要的额外功能)。

2.2.2 SpringMVC框架

Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦。请求驱动,就是请求-响应这种设计模型。

相关的概念解释如下:

  • 模型,Model指的是封装了应用程序数据的POJO。
  • 视图,View指的是负责呈现模型数据的HTML页面。
  • 控制器,Controller负责处理用户的请求,处理数据并生成相应的模型,然后把生成好的模型传递给相应的视图解析器,由视图解析器解析生成相关的HTML页面。

SpringMVC执行流程图如下:

6-springmvc执行流程

实际SpringMVC处理请求,主要是查看DispatcherServlet.doDispatch()源码的处理,先截取其部分关键源码如下:

public class DispatcherServlet extends FrameworkServlet {
    // ...

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
		ModelAndView mv = null;
        Object dispatchException = null;
        try {
	        processedRequest = this.checkMultipart(request);
	        // 基于请求request获取相应的处理执行链(责任链)
	        mappedHandler = this.getHandler(processedRequest);
	        if (mappedHandler == null || mappedHandler.getHandler() == null) {
	            this.noHandlerFound(processedRequest, response);
	            return;
	        }
	        // 获取相应的处理适配器
            HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
            // handle方法内部是调用实际的业务处理方法(动态代理)
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
            // 获取对应的视图名称
            this.applyDefaultViewName(processedRequest, mv);
            // 处理拦截器定义的业务
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        } catch (Exception var20) {
            dispatchException = var20;
        } catch (Throwable var21) {
            dispatchException = new NestedServletException("Handler dispatch failed", var21);
        }
        // 加载模型,渲染视图
        this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
	}

  // ...
}

基于源码和执行流程图,详解流程步骤如下:

  • 客户端或浏览器发起请求到前端控制器DispatcherServlet
  • 前端控制器请求处理器映射器HandlerMapping,查找出相应的处理执行链对象HandlerExecutionChain

项目启动加载时会初始化处理器映射器。它是一个包含所有业务对应的处理执行链的容器((一个处理执行链肯定会包含如业务标识URI、业务方法名、业务拦截器列表等信息)。这个处理执行链对象可能会包含多个HandlerInterceptor拦截器对象。真正执行业务方法时,会逐步执行拦截器。这是典型的责任链设计模式,处理器执行对象拦截器对象可以自行添加。

  • 前端控制器基于处理执行链对象HandlerExecutionChain,获取相应的处理器适配器对象HandlerAdapter
  • 基于处理器适配器HandlerAdapter.handle()去执行真正的业务方法,并返回模型视图对象ModelAndView(业务方法的执行,这里很明显使用的就是动态代理设计模式。ModelAndView是springmvc框架的一个底层对象,包括Modelview
  • 前端控制器将模型视图对象ModelAndView传递给视图解析器,由视图解析器进行视图解析 (根据逻辑视图名解析成真正的视图(jsp))并返回视图View,通过这种策略很容易更换其他视图技术,只需要更改视图解析器即可
  • 前端控制器进行视图渲染 (视图渲染将模型数据(在ModelAndView对象中)填充到request域)后,响应用户。

实际测试SpringMVC进行业务解耦的源码内容如下(可以自行debug测试,核对SpringMVC执行流程):

  1. 首先在pom.xml文件中导入必要依赖如下:
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>4.3.7.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.16.8</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>[2.9.10.1,)</version>
</dependency>
  1. 除了设置web.xml的内容,还需要在spring-mvc-servlet.xml中定义视图解析器并开启注解驱动;
<!-- 注意配置命名空间 -->
<beans>
  <mvc:annotation-driven/>

  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix">
      <value>/WEB-INF/jsp/</value>
    </property>

    <property name="suffix">
      <value>.jsp</value>
    </property>
  </bean>
</beans>
  1. 基于视图解析器的配置,在目录/WEB-INF/jsp/下定义视图hello.jsp如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<p>姓名:${user.name}</p>
<p>花名:${user.nick}</p>
<p>年龄:${user.age}</p>
<p>爱好:${user.hobby}</p>
</body>
</html>
  1. 定义好业务方法如下:
@Controller
@RequestMapping("/users")
public class UserPageController {

    @RequestMapping("/page")
    public ModelAndView showPage(){

        User user = new User();
        user.setName("戴振焱");
        user.setNick("zhenye");
        user.setAge(27);
        user.setHobby("动漫、炉石");
        ModelAndView modelAndView = new ModelAndView();
        // 处理并生成相应的模型user
        modelAndView.addObject(user);

        //指定视图
        modelAndView.setViewName("hello");
        return modelAndView;
    }
}
@RestController
@RequestMapping("/users")
public class UserJsonController {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    @GetMapping(value = "/json", produces="text/html;charset=UTF-8")
    public String showJson() {
        User user = new User();
        user.setName("戴振焱");
        user.setNick("zhenye");
        user.setAge(27);
        user.setHobby("动漫、炉石");
        String userInfo = null;
        try {
            userInfo = OBJECT_MAPPER.writeValueAsString(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return userInfo;
    }
}

由于开启了注解驱动<mvc:annotation-driven/>,Spring容器会自动检测所有的类注解@Controller@RestController
@Controller表示需要使用视图解析器ViewResolver,其所有方法的返回值都是映射/WEB-INF/jsp/目录下查找所有的视图(如这里的viewNamehello,就是去找视图 /WEB-INF/jsp/ + hello + .jsp)。
@RestController则表示不使用视图解析器,直接给用户返回相应格式的数据(这里的json字符串)。

  1. war包并部署到tomcat容器中后,测试接口的效果图如下:

7-springmvc视图解析效果图

上述相关源码详见我的github

2.2.3 Mybatis/JPA框架

MybatisJPA是两种ORMObject/Relational Mapping,对象关系映射)的框架。简单来说,这两个框架来维护java-bean与数据表的关系,开发人员只需关注业务逻辑本身。
这两个框架各有优缺点。

  • JPAJava Persistence API及Java持久层API。它是一种java持久层的实现规范。引入该框架后,开发人员可以不用写SQL语句,利用该框架提供的API直接操作数据库表。
  • Mybatis,其前身是ibatis。它支持定制化 SQL、存储过程以及高级映射。
    这两个框架优劣势及其明显。如果项目业务简单且后期扩展功能较少,推荐选用JPA。绝大部分业务都是单表操作,使用该框架可以极大地提升开发效率。否则最好选用Mybatis框架,其支持编写原生SQL语句,更加灵活,后期扩展功能时更易实现。

Mybatis框架为例,简单介绍如何使用这些ORM框架。

  1. 首先,在pom.xml文件中导入必须的依赖如下:
<dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>4.3.7.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.2</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>6.0.6</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.8</version>
    </dependency>
  </dependencies>
  <!-- maven工程默认只加载java文件。要加载xml文件,必须添加如下额外配置 -->
  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>
  1. 新建数据库表以及该表对应的实体类

建库建表语句如下:

CREATE DATABASE IF NOT EXISTS easy-mybatis;
USE easy-mybatis;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) DEFAULT NULL,
  `nick` varchar(32) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `hobby` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

user表对应的实体类如下:

@Getter
@Setter
@ToString
public class User {
  private Long id;
  private String name;
  private String nick;
  private Integer age;
  private String hobby;
}
  1. 编辑Mybatis的配置文件mybatis-config.xml的内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/easy-mybatis?serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="com/netopstec/easy_mybatis/mapper"/>
    </mappers>
</configuration>
  1. 编辑接口以及对应的映射XMl文件内容如下:

接口层代码如下:

public interface UserMapper {
  List<User> selectAll();
  int insertOne(User user);
}

对应映射文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.netopstec.easy_mybatis.mapper.UserMapper">
    <select id="selectAll" resultType="com.netopstec.easy_mybatis.entity.User">
        SELECT * FROM `user`
    </select>

    <insert id="insertOne" parameterType="com.netopstec.easy_mybatis.entity.User">
        INSERT INTO `user` (id, name, nick, age, hobby)
        VALUES (#{id}, #{name}, #{nick}, #{age}, #{hobby})
    </insert>
</mapper>
  1. 测试代码如下:
public class MybatisTest {

    public static void main(String[] args) throws IOException {
        InputStream reader = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.selectAll();
        System.out.println("新增之前,user表数据:" + userList);
        User user = new User();
        user.setName("戴振焱");
        user.setNick("zhenye");
        user.setAge(27);
        user.setHobby("动漫,炉石");
        userMapper.insertOne(user);
        userList = userMapper.selectAll();
        System.out.println("新增之后,user表数据:" + userList);

    }
}

最终的测试效果图如下:

8-mybatis测试效果图

上述相关源码详见我的github

2.2.4 SpringBoot框架

SpringBoot框架的核心思想是:“约定优于配置”。
整合一个基于Java-Spring开发处理的项目,一般都需要进行非常多的额外配置。如上面需要使用Mybatis框架时,需要新建并完善mybatis-config.xml配置文件中的内容。这对于对该框架或其配置项不熟的新手来说,非常的不友好。
SpringBoot就对一些常用的第三方工具包的常用配置进行了整合。基于SpringBoot框架开发项目,当导入SpringBoot整合后提供的依赖包(官方项目常常以spring-boot-starter开头)后,它会为我们开发的项目添加一下默认的配置。如上面的数据源的配置,我们可以导入spring-boot-starter-jdbc对应的依赖包,在配置文件中添加必要的四个配置(spring.datasource.url,spring.datasource.driver-class-name,spring.datasource.username,spring.datasource.password)即可使用。
当前SpringBoot版本支持自动配置的第三方工具参考源码spring.factories内容,如下图:

9-springboot源码

现以开发一个自定义的starter项目为例,进行说明。

假设有一个日常作息时间表如下:

默认时间节点事项对应配置项字段
08:00起床时间/睡觉结束时间sleepTimeEnd
08:30早餐开始时间breakfastTimeStart
09:00早餐结束时间breakfastTimeEnd
12:00午餐开始时间luntchTimeStart
12:30午餐结束时间luntchTimeEnd
19:00晚餐开始时间dinnerTimeStart
19:30晚餐结束时间dinnerTimeEnd
00:00睡觉开始时间sleepTimeStart

现在开发一个相应项目plan-spring-boot-starter,需要该项目提供如下功能:

  • formatPlanList(),打印现在的作息时间表。
  • doing(Date time),确认按照作息时间,该时间点正在做什么。
  • nextToDo(Date time),确认按照作息时间,该时间点下一步要做的什么。
  • 所有事项对应的时间节点都可以自行配置。

新建一个maven项目—plan-spring-boot-starter,其最终目录如下:

10-plan-springboot-starter项目结构

  • 首先,在pom.xml文件中导入spring-boot自动配置实现必要的依赖包如下:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
    <version>1.5.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <version>1.5.2.RELEASE</version>
    <optional>true</optional>
</dependency>
  • 然后,编辑可自动配置的配置类PlanProperties如下:
@Getter
@Setter
@ConfigurationProperties(prefix = "spring.plan")
public class PlanProperties {

    /**
     * 起床时间/睡觉结束时间
     */
    private String sleepTimeEnd = "08:00";

    /**
     * 早餐开始时间
     */
    private String breakfastTimeStart = "08:30";

    /**
     * 早餐结束时间
     */
    private String breakfastTimeEnd = "09:00";

    /**
     * 午餐开始时间
     */
    private String lunchTimeStart = "12:00";

    /**
     * 午餐结束时间
     */
    private String lunchTimeEnd = "12:30";

    /**
     * 晚餐开始时间
     */
    private String dinnerTimeStart = "19:00";

    /**
     * 晚餐结束时间
     */
    private String dinnerTimeEnd = "19:30";

    /**
     * 睡觉开始时间
     */
    private String sleepTimeStart = "00:00";
}
  • 然后,编写实现了上述三个功能(打印现在的作息时间表formatPlanList(),确认当前正在做什么doing(Date time),确认下一步要做什么nextToDo(Date time))的业务功能类PlanService如下:
public class PlanService {

    private PlanProperties planProperties;

    public PlanService(){}

    public PlanService(PlanProperties planProperties) {
        this.planProperties = planProperties;
    }

    public String formatPlanList() {
        // ... //
        return plan;
    }

    public String doing(Date date) {
        // ... //
        return doingThing;
    }

    public String nextTodo(Date date) {
        // ... //
        return nextTodo;
    }
}
  • 编辑由Spring容器帮我们管理的自动配置类PlanServiceAutoConfiguration如下:
@Configuration
@EnableConfigurationProperties(PlanProperties.class)
@ConditionalOnClass(PlanService.class)
@ConditionalOnProperty(prefix = "spring.plan", value = "enabled", matchIfMissing = true)
public class PlanServiceAutoConfiguration {
    @Autowired
    private PlanProperties properties;

    @Bean
    @ConditionalOnMissingBean(PlanService.class)
    public PlanService planService(){
        PlanService planService = new PlanService(properties);
        return planService;
    }
}
  • 最后,确认让SpringBoot加载自动配置类,编辑文件spring.factories如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.netopstec.plan.PlanServiceAutoConfiguration

执行mvn clean install命令,对该自动配置项目进行打包即可。

新建一个测试该自动配置的SpringBoot项目—test-for-plan,然后在pom.xml导入上述自动配置依赖包如下图:

11-test-for-plan项目结构

启动该测试项目,执行测试代码效果图如下:

12-test-for-plan测试
很明显地能够看到,注入业务功能类PlanService后,可以直接使用该业务功能类的各项功能方法。而且对应的配置项就是默认值。

在SpringBoot配置文件,修改这些配置项的内容(如:将早餐结束时间修改为"08:45",午餐结束时间修改为"12:15"),如下:

13-test-for-plan修改配置

再次执行测试方法,效果如下:

14-test-for-plan再次测试
很明显地看到,这个项目实现了自动配置的功能。而且也符合实际使用自动配置的逻辑。在项目配置文件中中新加了配置项内容后,其内容会覆盖配置项的默认值。

上述相关源码详见:

  • 10
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
提供典型应用案例,剖析JSP/Servret技术与Struts 2技术在Web开发中的不同 提供完整的应用案例,使读者可以深入体会SSH开发模式的精髓 所有开发工具和框架均使用目前的最新版本,紧跟技术发展的趋势 提供230个实例和4个综合案例,可以作为案头必备的查询手册 一线开发人员全力打造,分享技术盛宴! 重点内容及特色 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》介绍了Web开发中客户端技术的基础知识,包括JavaScript、CSS、AJAX等,这些技术都是Web应用中常用的客户端技术。 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax+》讲解了JSP/S rvlet技术的基础知识,并提供了一个综合案例展示其具体应用,它们是Java Web服务端技术的基石,也是学习Java Web开发所要必须掌握的技术。 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》重点讲解了Struts 2、Speing和HIbernate框架的基础知识和高级技术,如Sruts 2中的*、类型转换、国际化和标签等,HIbe rna{e的会话、0/R映射和事务管理等,Spring中的数据库技术与AOP等。 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》特别介绍了Struts 2对AjAX的支持,还重点剖析了SSH框架的整合开发,并给出了两个综合案例来展示整合SSH框架开发Web应用。 和已经出版的同类图书相比,《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》讲解由浅入深,涵盖更多内容,列举了大量典型实例具有超强的实用性,另外,《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》各篇独立,适合读者全面学习或对部分内容重点学习。 读者对象 有Java基础,想进一步学习SSH框架整合开发的人员 了解SSH整合开发,想进一步提高开发技术的人员 正在使用SSH整合技术开发项目,想查阅资料的人员 大中专院校的学生和老师,以及Java培训班的学员和讲师 需要一本案头必备查询手册的程序员 光盘内容 6小时多媒体体视频讲解 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》所涉及的源代码 布衣暖,菜根香,好书滋味长!清华大学出版社长期以来一直秉承为读者多出好书的宗旨,多年来为读者奉献了大量脍炙人口的精品图书。尤其在计算机图书出版领域更是形成了鲜明特色,所出版的各类计算机图书受到了广大读者的好评。本次出版的“原创经典,程序员典藏”系列图书是清华大学出版社的重点精品计算机图书,旨在帮助读者全面学习各类程序设计语言和开发工具,提高开发水平。同时也为广大程序员提供良好的技术参考,以便作为案头必备的查询手册。 内容提要 -------------------------------------------------------------------------------- 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》通过对SSH中的各种技术循序渐进地讲解,使读者尽快掌握开发基于SSH的Web程序的方法。《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》内容包括Web客户端技术、JSP/Servlet技术、Struts 2(*、类型转换、输入校验、上传和下载文件、Struts 2的各种标签、对 AJAX的支持等)、Spring(Ioc容器、装配Java Bean、Jdbc和Hibernate模板、事务管理、Spring AOP等)以及 Hibernate(会话、映射、标准查询API、HQL、事务管理、锁等)。除此之外,《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》还提供了两个完整的实例来讲解开发SSH的详细步骤和方法。通过对这两个实例的学习,读者可以对SSH开发模式有更透彻地理解和认识。SSH是目前最流行的Java Web开发技术。 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》适合广大从事Java Web开发工作的技术人员、对SSH开发感兴趣的人员以及大专院校学生阅读,尤其是具有一定的Web开发经验的技术人员。 目录 -------------------------------------------------------------------------------- 第1篇 web开发基础篇 第1章 搭建开发环境 1.1 本书使用的软件和框架的版本 1.2 JDK6的下载与安装 1.3 Eclipse3.4 的下载与安装 1.4 MyEclipse6.5 的下载与安装 1.5 Eclipse:IDEforJavaEEDevelopers的下载与安装 1.6 Tomcat6的下载与安装 1.7 在MyEclipse中配置。Tomcat 1.8 在EclipseIDEforJavaEEDevelopers中配置Tomcat 1.9 小结 第2章 JavaWeb应用开发基础 2.1 Web技术的发展 2.2 JavaWeb技术 2.2.1 Java.Welb程序的基本组成 2.2.2 JavaWeb程序的目录结构 2.2.3 JavaWeb程序的配置文件 2.3 MVC模式与MvC框架 2.3.1 JSP模型1和JSP模型2 2.3.2 Web应用程序需要的基础服务 2.3.3 MVC模式概述 2.3.4 常用的MvC框架 2.4 小结 第3章 Web开发中的客户端技术 3.1 常用的JavaScriptIDE简介 3.1.1 在MyEclipse中使用JavaScript 3.1.2 在EclipseIDEforJavaEE中使用JavaScript 3.1.3 在NetBeans中使用JavaScript 3.1.4 其他的JavaScriptIDE 3.2.1 avaScdpt语法基础 3.2.1 实例:编写第一个JavaScript程序:Greet 3.2.2 变量 3.2.3 原始类型 3.2.4 类型转换 3.2.5 函数与函数调用 3.2.6 类和对象 3.3 JavaScript高级技术 3.3.1 DOM技术概述 3.3.2 获得HTML元素的3种方法 3.3.3 实例:图像自动切换 3.3.4 正则表达式 3.3.5 实例:表格排序 3.4 CSS基础 3.4.1 CSS的基本语法 3.4.2 在Style属性中定义样式 3.4.3 在HTML中定义样式 3.4.4 在外部文件中定义样式 3.4.5 样式的继承 3.5 AJAX.基础 3.5.1 AJAX概述 3.5.2 实例:使用XMLHttpRequest获得Web资源 3.5.3 实例:使用XMLHttpRequest跨域访问Web资源 3.5.4 实例:AJAX的3种交换数据方法 3.6 小结 第4章 Servlet技术 4.1 Servlet的Helloworld程序 4.1.1 实例:在My Eclipse中编写Helloworld程序 4.1.2 实例:手工编写:Helloworld程序 4.2 Servlet基础 4.2.1 配置数据库连接池 4.2.2 数据库连接池的应用 4.2 -3实例:用doGet方法处理客户端请求 4.2.4 实例:用doPost方法处理客户端请求 4.2.5 实例:用service方法处理客户端请求 4.2.6 实例:初始化(init)和销毁(destroy)Servlet 4.2.7 实例:使用PrintWriter输出响应消息 4.2.8 实例:用ServletOutputStream显示图像 4.2.9 实例:使用RequestDispatcher包含Web资源 4.2.10 实例:使用RequestDispatcher转发Web资源 4.3 HttpServletResponse类的其他功能 4.3.1 产生状态响应码 4.3.2 设置响应消息头 4.3.3 实例:验证响应头设置情况 4.4 使用:HttpServletRequest获得请求消息 4.4.1 获取请求行消息 4.4.2 获取网络连接消息 4.4.3 获取请求头消息 4.5 处理Cookie 4.5.1 什么是Cookie 4.5.2 Cookie类中的方法 4.5.3 实例:用Cookie读写客户端信息 4.5.4 实例:用Cookie读写复杂数据 4.6 处理Session 4.6.1 什么是Session 4.6.2 HttpSession接口中的方法 4.6.3 HttpServletRequest接口中的Session方法 4.6.4 实例:通过Cookie跟踪Session 4.6.5 实例:通过重写uRL跟踪Session 4.7 Web开发的中文问题 4.7.1 Java的编码原理 4.7.2 实例:解决输出中文乱码问题 4.7.3 实例:解决服务端程序读取中文请求消息的乱码问题 4.7.4 实例:用AJAX技术发送和接收中文信息 4.7.5 实例:在请求消息头和响应消息头中转输中文 4.8 小结 第5章 JSP技术 5.1 用MyEclipse编写第一个JSP程序 5.1.1 实例:编写显示服务器当前时间的JSP程序 5.1.2 调试JSP程序 5.1.3 改变JSP的访问路径和扩展名 5.1.4 手动发布JSP程序 5.2 JSP的运行原理 5.2.1 Tomcat如何处理JSP页 5.2.2 分析由JSP生成的Servlet代码 5.3 JSP基本语法 5.3.1 JSP表达式 5.3.2 在JSP中嵌入Java代码 5.3.3.JSP声明 5.3.4.JSP表达式语言(EL) 5.3.5 实例:用EL函数替换HTML中的特殊字符 5.3.6 JSP页面中的注释 5.4 JSP指令 5.4.1 JSP指令简介 5.4.2 page页面指令 5.4.3 include加入指令 5.5.JSP的9个内置对象 5.5.1 out输出对象 5.5.2 pageContext封装对象 5.5.3 其他的JSP内置对象 5.6 JSP标签 5.6.1 插入标签 5.6.2 转发标签 5.6.3 传参标签 5.6.4 创建:Bean标签 5.6.5 设置属性值标签 5.6.6 获取属性值标签 5.7 JSP的标准标签库(JSTL) 5.7.1 如何使用JSTL 5.7.2 条件标签 5.7.3 循环标签 5.8 小结 第6章 用Servlet和JSP实现注册登录系统 第2篇 Struts 2篇 第7章 编写Struts 2的第一个程序 第8章 Struts 2进阶 第9章 Struts 2的* 第10章 Struts 2的类型转换 第11章 Struts 2的输入校验 第12章 文件的上传和下载 第13章 国际化 第14章 Struts 2的标签库 第15章 Struts 2对AJAX的支持 第16章 用Struts 2实现注册登录系统 第3篇 Hibernate篇 第17章 Hibernate的Helloworld程序 第18章 配置Hibernate 第19章 Hibernate的会话与O/R映射 第20章 Hibernate的查询与更新技术 第21章 Hibernate的高级技术 第4篇 Spring篇 第22章 Spring的Helloworld程序 第23章 反向控制(Ioc)与装配JavaBean 第24章 Spring中的数据库技术 第25章 Spring的其他高级技术 第5篇 综合实例篇 第26章 Struts 2与Hibernate、Spring的整合 第27章 网络硬盘 第28章 论坛系统

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值