前置基础框架

Spring家族介绍与开发环境

课程主要内容

  • Spring能做什么?

  • Spring开发环境搭建

  • HelloWorld程序

Spring能做什么?

Spring是一个轻量级的控制反转(IoC/di)和面向切面编程(AOP) 的对象容器框架

Spring官网:http://spring.io/

Spring 是一个于 2003 年兴起的一个轻量级的 Java 开源开发框架

如今Spring已是Java项目的标配,它极大的简化了开发过程,降低了开发难度。

  • 方便解耦,简化开发;

  • AOP 编程的支持;

  • 声明式事务的支持;

  • 方便程序的测试;

  • 方便集成各种优秀框架。

IoC

Inversion of Control

AOP

Aspect Oriented Programming

Spring5新特性

Spring5 是一个重要的版本,距离SpringFramework4差不多四年

  • 支持JDK8

    • Spring 接口中的默认方法

    • 基于 Java8 反射增强的内部代码改进

    • 在框架代码中使用函数式编程 - lambda表达式 和 stream流

  • 响应式编程支持Spring Web Reactive异步的、非阻塞的、事件驱动的服务

  • 支持J2EE7

    • Servlet 3.1

    • JMS 2.0

    • JPA 2.1

    • JAX-RS 2.0

  • Bean Validation 1.1

  • Hibernate 5

  • Jackson 2.6

  • EhCache 2.10

  • JUnit 5

  • Tiles 3

  • Kotlin

开发环境

Spring Jar包

SpringFramework官网下载地址:

https://repo.spring.io/libs-release-local/org/springframework/spring/

解压缩Jar包可以看见如下结构

  • Doc 文档

  • Libs Jar包

  • Schema XML约束

  • license.txt 许可协议

  • notice.txt 注意事项

  • readme.txt 读我

常用Jar包

spring-core框架的基础功能,包括IOC和AOP功能
spring-aspects提供了与AspectJ的集成,AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
spring-beans所有应用都要用到,包含访问配置文件、创建和管理 bean 以及进行 Inversion of Control(控制反转) / Dependency Injection(依赖注入)操作相关的所有类。外部依赖 spring-core
spring-context 
spring-aop、spring-instrument面向切面编程、植入代理
spring-expression模块提供了强大的表达式语言去支持查询和操作运行时对象图。这是对JSP 2.1规范中规定的统一表达式语言的扩展。该语言支持设置和获取属性值,属性分配,方法调用,访问数组,集合和索引器的内容,逻辑和算术运算,变量命名以及从Spring的IoC容器中以名称检索对象。 它还支持列表投影和选择以及常见的列表聚合。
spring-messaging消息传递
spring-jdbc、spring-jms、spring-orm数据访问支持
spring-jclJakarta Commons Logging采用了设计模式中的“适配器模式”,它对外提供统一的接口,然后在适配类中将对日志的操作委托给具体的日志框架。
spring-tx事务
spring-webmvc、spring-webWebmvc框架支持
spring-webfluxServlet3.1 + Netty 方式的WebMvc
spring-websocket对ws支持

commons-logging

运行Spring程序额外还需要commons-logging包

http://commons.apache.org/proper/commons-logging/download_logging.cgi

开发工具

可以使用Eclipse、Idea等

推荐使用官方开发工具STS

https://spring.io/tools

环境变量

window下配置

  • 新建->变量名"JAVA_HOME",变量值"C:\Java\jdk1.8.0_05"(即JDK的安装路径)

  • 编辑->变量名"Path",在原变量值的最后面加上“;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin”

  • 新建->变量名“CLASSPATH”,变量值“.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar”

在控制台分别输入java,javac,java -version 命令,测试环境是否设置成功

Hello world

新建java项目

包引入

配置文件

在src下新建

applicationContext.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"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
        "src/applicationContext.xml"
        <bean id="user" class="com.msb.User"></bean>
</beans>

Bean

建立准备由Spring管理的Bean

包含两个属性,生成get/set方法

    private String name;
    private Integer age;

测试类

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User)ctx.getBean("user");
        user.setName("uu");
        user.setAge(18);
        System.out.println(ToStringBuilder.reflectionToString(user));;

ToStringBuilder 工具类

  • Commons项目中用来处理Java基本对象方法的工具类包,可以简化很多平时经常要用到的写法,例如判断字符串是否为空等等。

  • 是一个最常用的工具,作为jdk的补充。

  • Lang下有很多Utils类,提供了若干static方法供调用,涵盖了字符串操作、字符操作、JVM交互操作、归类、异常和位域校验等等。

项目地址

http://commons.apache.org/proper/commons-lang/download_lang.cgi

 

Spring是一个对象管理容器,自动化完成了创建、初始化、销毁等工作。

传统的方式

Person person = new Person();

person.setAge(18);

person.setName("zhangsan");

IoC概念

IoC是一个概念,是一种思想,其实现方式多种多样。当前比较流行的实现方式之一是DI

基于XML的DI

ApplicationContext.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">

XML文件结构

  1. <beans  beans是xml文件的根节点 
  2. xmlns=http://www.springframework.org/schema/beans xmlns=xml NameSpace 类似于java中的package
  3. xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi是指xml文件遵守xml规范,xsi全名:xml schema instance 
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans.xsd"> 是指具体用到的schema资源

真的去网上找xsd文件?

当然不是

spring在加载xsd文件时总是先试图在本地查找xsd文件(spring的jar包中已经包含了所有版本的xsd文件),如果没有找到,才会转向去URL指定的路径下载

验证PluggableSchemaResolver.class中

=后面是包名以及具体xsd文件位置

多配置文件

ApplicationContext加载多文件

new ClassPathXmlApplicationContext("applicationContext.xml","application-service.xml");

引入外部文件

<import resource="application-service.xml"/>

Bean的定义与注册

Spring的配置文件是用于指导Spring工厂进行Bean的生产、依赖关系注入及Bean实例分发的“图纸”,它是一个或多个标准的XML文档

<bean id="food" class="com.msb.Food"></bean>

一个bean只能有一个id,但是可以有多个name作为别名

Alias 别名

<alias name="user" alias="my_user_bean" />

spring ioc container

spring ioc container 管理一个或多个bean,bean来自xml中对bean定义的元数据(configuration metadata) 

元数据信息

Class

Name,id

标识

Scope

作用域

Constructor arguments

构造器注入

Properties

属性注入

autowiring mode

自动装配

lazy-initialization mode

懒加载

initialization method

初始化

destruction method

销毁

构造器注入 constructor-arg

Person的构造器

public Person(String name, Integer age, Food food) {

super();

this.name = name;

this.age = age;

this.food = food;

}

Xml

指定name

        <bean id="person"  class="com.msb.Person">

         <constructor-arg name="age"  value="18"></constructor-arg>

         <constructor-arg name="name"  value="zhangsan"></constructor-arg>

        </bean>

指定类型

<constructor-arg type="int" value="7500000"/>

指定index

<constructor-arg index="0" value="7500000"/>

属性注入

    <bean id="person"  class="com.msb.Person">

           <property name="age"  value="19"></property>

        <property name="name"  value="zhangsan"></property>

        </bean>

使用p-namespace

属性注入

添加一个namespace

xmlns:p=http://www.springframework.org/schema/p

使用 p

<bean id="person" class="com.msb.Person"  p:age="21" p:name = "zhangsan">

<bean id="person" class="com.msb.Person"  p:age="21" p:name = "zhangsan" p:food-ref="food">

使用c- namespace

构造器注入

<bean id="foo" class="x.y.Foo" c:bar-ref="bar" c:baz-ref="baz" c:email= "foo@bar.com"/>

使用java.util.Properties

在set方法中把properties

private Properties properties;

public void setProperties(Properties properties) {

this.properties = properties;

this.name=properties.getProperty("name");

}

对其他Bean的引用

<property name="food" ref="food"></property>

<bean id="food" class="com.msb.Food"></bean>

集合

Array

private String[] myArray;

 

<property name="myArray">

<array>

<value>北京</value>

<value>上海</value>

</array>

</property>

Properties

private Properties adminEmails;

 

  <property name="adminEmails">

          <props>

              <prop key="administrator">administrator@example.org</prop>

              <prop key="support">support@example.org</prop>

              <prop key="development">development@example.org</prop>

          </props>

      </property>

List

private List someList;

 

   <property name="someList">

          <list>

              <value>apple</value>

              <value>orange</value>

          </list>

</property>

Map

private Map someMap;

 

<property name="someMap">

          <map>

              <entry key="an entry" value="just some string"/>

              <entry key ="a ref" value-ref="food"/>

          </map>

</property>

 

depends-on 提前初始化

可以使某个bean在创建前,先创建别的bean

lazy-init

在容器启动后,bean被使用到的时候才加载。可以使用的lazy-init属性

bean id="person" class="com.msb.Person" lazy-init="false"

 

作用域

spring为bean提供了6种作用域,其中4种只有在web-aware的ApplicationContext种才有用。用户也可以创建自定义的作用域。

singleton 、prototype 、websocket、request、session、application

singleton scope 单例作用域

每一个类,在一个容器内只能产生一个实例

prototype scope 原型作用域

bean每次被注入,或者使用getBean()方法获取时,都返回一个新的实例。

Request scope

该作用域的bean,在每个HTTP request都会新建一个实例,当一个request结束后,该实例也会被丢弃。

Session scope

某一个用户在一段时间内,会使用同一个session,session有超时时间,过了超时时间则session失效。不同用户使用不同的session。

Application scope

该作用域的bean,每一个application会创建一个

MVC下Spring的单例

想在一个singleton内多次调用短存活时间的bean(propotype、request、session等),希望调用的是不同的实例,那么就需要使用AOP proxy技术

线程安全问题

业务对象并没有做线程的并发限制,因此不会出现各个线程之间的等待问题,或是死锁问题

MVC中的实体bean不是单例的

成员变量

在并发访问的时候这些成员变量将会是并发线程中的共享对象,也是影响线程安全的重要因素

引用类型的成员

其中引用类型的成员变量即我们在controller中注入的service,在service中注入的dao,这里将其定义为成员变量主

要是为了实例化进而调用里面的业务方法,在这些类中一般不会有全局变量,因此只要我们的业务方法不含有独立的

全局变量即使是被多线程共享,也是线程安全的。

Controller service dao 层中的业务类是多线程共享的,但是每个线程在处理数据的时候具体处理的数据是在每个线程中各自有一份。

controller层

  1. final类型 线程安全
  2. 成员变量 有状态数据有线程安全问题

循环依赖的bean

构造器注入循环依赖

创建3个类

循环引用属性

A类中 -> B类的一引用 -

当循环依赖的bean都是通过构造器注入依赖的时候,无论这些bean是singleton还是prototype,在获取bean的时候都会失败。

通过属性注入

  1. 循环依赖的bean都是singleton 成功
  2. 循环依赖的bean都是prototype 失败
  3. 同时有singleton和prototype 当先获取的那个bean是singleton时,就会成功,否则失败

Spring容器在创建A时,会发现其引用了B,从而会先去创建B。同样的,创建B时,会先去创建C,而创建C时,又先去创建A。最后A、B、C之间互相等待,谁都没法创建成功

IoC与动态代理

Maven方式创建Spring工程

工程创建

1.新建项目 选择Maven Project

2.勾选 Create a simple project

3.添加项目信息

  • Group id :包名

  • Artifact id:标识名

  • Name:项目名

依赖引入

Maven 中央仓库

地址https://mvnrepository.com/

使用国内镜像

创建一个maven的配置文件

参照:

http://maven.apache.org/settings.html

Pom.xml

```xml
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.1.7.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.7.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.1.7.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.9</version>
    </dependency>
```

空值注入

Value标签

标识空值 或空字符串 “”

<property name="name"><value></value></property>

Null标签

标识Null

<property name="name"><null></null></property>

工厂方式注入

为满足更复杂的需求,Spring也提供了工厂方式来创建更加灵活的Bean。

留意观察工厂类和实现类的创建次数

动态工厂

抽象接口 Car

public interface Car {
​
     public String getName();
​
     public String getPrice();
​
}

实现类 BMW车

public class Bmw implements Car{
​
 
​
     public String getName() {
​
            // TODO Auto-generated method stub
​
            return "别摸我";
​
     }
​
     public String getPrice() {
​
            // TODO Auto-generated method stub
​
            return "500000RMB";
​
     }
​
}

汽车工厂类 CarFactory

public class CarFactory {
​
    public Car getCar(String name) throws Exception{
        
        if (name.endsWith("bmw")) {
            return new Bmw();
        }else {
                throw new Exception("car not fond");
        }
    }
}

Bean配置

<bean id="carFactory" class="com.msb.CarFactory"></bean>
<bean id="car" factory-bean="carFactory" factory-method="getCar" >
    <constructor-arg value="bmw"></constructor-arg>
</bean>

静态工厂

Bean配置

<bean id="carStatic" class="com.msb.CarFactoryStatic" factory-method="getCar">
 <constructor-arg value="bmw"></constructor-arg>
</bean>

工厂类

public class CarFactoryStatic {

	public static Car getCar(String name) throws Exception{
		
		if (name.endsWith("bmw")) {
			return new Bmw();
		}else {
				throw new Exception("car not fond");
		}
	}
}

autowire自动注入

使用自动需要在配置文件中bean上添加autowire

<bean id="person" class="com.msb.Person" autowire="byName">
</bean>
<bean id="pet" class="com.msb.Pet">
 	<property name="name" value="kele"></property>
</bean>

实体

public class Person {

	private String name;
	private Pet pet;
}
public class Pet {

	private String name;
}

可选两种类型

byName

byName方式自动注入:要求注入的bean的id必须和被注入的bean对象的属性名一致

byType

byType方式自动注入:要求注入的bean的对象类型与被注入的bean对象类型一致,并且在配置文件中的Bean相同类型必须唯一

如果存在多个,会抛异常:

No qualifying bean of type 'com.msb.Pet' available: expected single matching bean but found 2: pet,pet2

全局自动注入

在首行Beans标签下添加default-autowire属性。

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans.xsd"
	
	default-autowire="byType"
	>

annotation注解注入

使用注解需要导入AOP包

在配置文件中添加Context约束

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
	http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context			http://www.springframework.org/schema/context/spring-context.xsd
	"
	>

context:component-scan

<context:component-scan base-package="com.msb"></context:component-scan>

component-scan可以自动扫描包内容,并注册Bean到Spring容器

@Component

在需要注册到容器的类上添加@Component标签,标识这个类由Spring容器接管

约定大于配置

在一个类上添加@Component默认会使用首字母小写的类名作为ID注册到Spring容器。

如果需要手动指定Bean Id可以使用@Component("p")

同属@Component的额外三个注解

@Controller @Service @Repository

这三个注意在MVC开发中会经常用到,除了注解名字和Component不一样之外,其余功能都一样。

Spring额外提供这三个注解的目的主要是为了区分MVC中每个类的区别。

@Scope

使用注解注册Bean 默认的作用域还是singleton,可以使用@Scope("prototype")改变对象作用域

@Value

在使用注解给对象注入值的时候,不再需要Get/Set方法

基础类型

使用@Value注解

	@Value("小明")
	private String name;

对象引用

	@Autowired
	private Pet MyPet;

使用@Autowired注解

默认是ByType的,如果需要ByName需要配合@Qualifier注解

	@Autowired()
	@Qualifier("p2")
	private Pet MyPet;

面向切面编程 代码增强 

AOP(Aspect Oriented Programming)面向切面编程。

面向切面,是与OOP(Object Oriented Programming)面向对象编程并列的编程思想。

Spring支持两种方法,那么我们在使用spring进行动态代理时究竟使用的哪一种方法呢?spring优先支持实现接口的方式,如果没有接口则使用cglib方式

代理 

通过代理可以隐藏目标类的具体实现;在不修改目标类代码的情况下能够对其功能进行增强。

  1. 委托类和代理类有相同的接口或者共同的父类
  2. 代理类为委托类负责处理消息,并将消息转发给委托类
  3. 委托类和代理类对象通常存在关联关系
  4. 一个代理类对象与一个委托类对象关联
  5. 代理类本身并不是真正的实现者!而是通过调用委托类的方法来实现功能!

静态代理

使用硬编码的方式增强原有方法

  1. 优点:可以做到不对目标对象进行修改的前提下,对目标对象进行功能的扩展和拦截。
  2. 缺点:因为代理对象,需要实现与目标对象一样的接口,会导致代理类十分繁多,不易维护,同时一旦接口增加方法,则目标对象和代理类都需要维护。

Girl -> 目标对象 -> 被包装/增强的对象

public class Girl implements Human{

public void eat() {

System.out.println("Em mmm.. mm..");

}

}

抽象接口

interface Human {

public void eat();

}

ProxyGirl 代理对象,包含对原对象方法的增强,通过构造方法传入原对象,并实现和原对象相同的接口,实现接口方法,便可以利用Java多态的特性,通过访问代理方法同时能够调起原对象的实现,并对其增强。

public class ProxyGirl implements Human {

private Human human;

public ProxyGirl() {

super();

}

 

public ProxyGirl(Human human) {

super();

this.human = human;

}

public void eat() {

System.out.println("chiqian");

human.eat();

System.out.println("chihou");

}

}

测试类

Girl girl = new Girl();

Human proxyGirl = new ProxyGirl(girl);

proxyGirl.eat();

动态代理

动态代理是指动态的在内存中构建代理对象(需要我们制定要代理的目标对象实现的接口类型),即利用JDK的API生成指定接口的对象,也称之为JDK代理或者接口代理。

  1. 目标对象实现了接口 JDK动态代理
  2. 目标对象没有实现口CGLib

JDK动态代理

CGLIB动态代理

底层ASM

《SpringBoot 2.x》入门:框架介绍与HelloWorld

  • MVC架构思想

  • 使用STS构建SpringBoot项目

  • 使用SpringBoot构建Mvc web项目

  • MVCWeb项目中的注入

  • 热部署

介绍

SpringBoot主要解决的是在微服务的架构下简化配置(有快速配置)、前后端分离、快速开发

优点:

  • 提供了快速启动入门

  • 开箱即用、提供默认配置

  • 内嵌容器化web项目

  • 没有冗余代码生成和xml配置要求

2.运行Demo

创建项目

创建SpringBoot项目的几种方式:

  • 官网的Initializr

  • 使用Eclipse、STS、Idea等IDE创建Maven项目并引入依赖

  • 使用STS插件的Spring Initializr创建项目

 

访问http://start.spring.io/ 进入Spring项目Initializr

生成下载demo.zip

导入项目

1.Import一个Maven项目

 

2.选择要导入的文件

 

3.项目骨架

 

启动项目

  • 直接run启动程序里的Main()方法

  • 安装过STS插件或使用STS可以在项目上右键RunAS->Spring Boot APP

运行成功提示信息:

 

如果运行报错,请参照常见问题。

个性化

修改启动banner

在resources目录下新建banner.txt

http://www.network-science.de/ascii/ 英文

https://www.degraeve.com/img2txt.php 图片

Eclipse的皮肤

菜单栏中

Help -> EclipseMarketplace

搜索Theme

 

傻瓜式安装这个,安装完成会提示重启,跟随指引选择喜欢的风格。

 

简单使用

application.properties

把所有的配置全放在这个文件里,方便统一管理,maven也可以做到

修改tomcat端口

server.port=90

修改项目路径

server.servlet.context-path=/demo

多个入口main方法,打包之后找不到入库类

<build>
   <plugins>
      <plugin>  
          <groupId>org.springframework.boot</groupId>  
          <artifactId>spring-boot-maven-plugin</artifactId>  
                <configuration>  
                    <mainClass>com.mashibing.MyApp</mainClass>  
                </configuration>  
            </plugin>  
        </plugins>
</build>

HelloWorld

RestController

RestController = @Controller+@ResponseBody

 

一个效果

@RestController
​
public class MyAppController {
​
    @RequestMapping("/")
    public Map<String, String>  index() {
        Map<String, String> map = new HashMap<>();
        
        map.put("aaa", "bbb");
        map.put("aaa", "bbb");
        map.put("aaa", "bbb");
        map.put("aaa", "bbb");
        return map;
    }

使用thymeleaf模板引擎

Pom.xml引用

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

Controller代码

@Controller
public class IndexController {
​
    @RequestMapping("/")
    public String index(ModelMap map) {
​
        // 加入一个属性,用来在模板中读取
        map.addAttribute("msg", "nihao~");
        return模板文件的名称,对应src/main/resources/templates/index.html
​
        return "index";
    }

模板文件代码

<h1 th:text="${msg}">hi!</h1>

稍微复杂的restful api应用

UserRestfulController

UserRestfulController
@RequestMapping("/")
@RestController
public class UserRestfulController {
​
    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long,User>());
    @RequestMapping(value="/User",method=RequestMethod.GET)
    public List<User> getUserList(){
        ArrayList<User> list = new ArrayList<>(users.values());
        return  list;
        
    }
    
    @RequestMapping(value="User",method=RequestMethod.POST)
    public String addUser(@ModelAttribute User user) {
        users.put(user.getId(), user);
        return "addUser Success";
        
    }
}
​

 

User

public class User {
​
    private Long id;
    private String loginName;
    private String password;
    private String nickName;
​

注入Service

UserRestfulController

    @Autowired
    private UserService userSrv;
    
    
    @RequestMapping(value="/User",method=RequestMethod.GET)
    public List<User> getUserList(){
​
        return  userSrv.getUserList();
    }
    
    @RequestMapping(value="User",method=RequestMethod.POST)
    public String addUser(@ModelAttribute User user) {
        String msg = userSrv.addUser(user);
        return msg;
        
    }

UserService

@Service
public class UserService {
    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long,User>());
​
    public List<User> getUserList() {
        ArrayList<User> list = new ArrayList<>(users.values());
        return list;
    }
​
    public String addUser(User user) {
        users.put(user.getId(), user);
        return "addUser Success";
        }
}

前端模板显示

  <h1>User list</h1>
  <table>
    <tr>
      <th>NAME</th>
      <th>loginName</th>
      <th>nickName</th>
    </tr>
    <tr th:each="user : ${list}">
      <td th:text="${user.id}">id</td>
      <td th:text="${user.loginName}">loginName</td>
      <td th:text="${user.nickName}">nickName</td>
    </tr>
  </table>
  <p>
    <a href="../home.html" th:href="@{/}">Return to home</a>
  </p>

常见问题

Pom.xml

Springboot项目必须要继承的parnet

 

Pom.xml第一行报错

 

进入本地库

for /r %i in (*.lastUpdated) do del %i

然后update

缺少或包错误

 

删掉 重新update

找不到主类

 

所有错误都解决后

Jar方式运行 首先得有这个jar包

先clean package 生成jar文件,然后再run main方法

找不到jdk

 

把jre的路径换成jdk的

启动后自动停止

 

《Spring Boot 2.x》表单提交与服务器端数据校验

静态资源访问

src/main/resources/static

src/main/webapp

视图层整合

Jsp

Pom

    <!-- jstl -->

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>jstl</artifactId>

</dependency>

<!-- jasper -->

<dependency>

<groupId>org.apache.tomcat.embed</groupId>

<artifactId>tomcat-embed-jasper</artifactId>

<scope>provided</scope>

</dependency>

Properties

spring.mvc.view.prefix=/WEB-INF/jsp/

spring.mvc.view.suffix=.jsp

 

jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body>

<table border="1" align="center" width="50%">

<tr>

<th>ID</th>

<th>Name</th>

<th>Age</th>

</tr>

<c:forEach items="${list }" var="user">

<tr>

<td>${user.userid }</td>

<td>${user.username }</td>

<td>${user.userage }</td>

</tr>

</c:forEach>

</table>

</body>

</html>

Controller

@Controller

public class UserController {

/*

 * 处理请求,产生数据

 */

@RequestMapping("/showUser")

public String showUser(Model model){

List<Users> list = new ArrayList<>();

list.add(new Users(1,"张三",20));

list.add(new Users(2,"李四",22));

list.add(new Users(3,"王五",24));

 

//需要一个Model对象

model.addAttribute("list", list);

//跳转视图

return "userList";

}

整合DAO层

Spring-data-jpa

Entity

  <h1>User list</h1>

 

  <table>

    <tr>

      <th>NAME</th>

      <th>loginName</th>

      <th>nickName</th>

    </tr>

    <tr th:each="city : ${list}">

      <td th:text="${city.id}">id</td>

      <td th:text="${city.name}">loginName</td>

    </tr>

  </table>

 

  <p>

    <a href="../home.html" th:href="@{/}">Return to home</a>

  </p>

Repository

public interface CityRepository extends JpaRepository<City, Integer> {

 

}

Properties

 

##端口号

server.port=8888

 

 

##数据库配置

##数据库地址

spring.datasource.url=jdbc:mysql://localhost:3306/erp?characterEncoding=utf8&useSSL=false&serverTimezone=UTC

##数据库用户名

spring.datasource.username=root

##数据库密码

spring.datasource.password=840416

##数据库驱动

spring.datasource.driver-class-name=com.mysql.jdbc.Driver

 

 

##validate  加载hibernate时,验证创建数据库表结构

##create   每次加载hibernate,重新创建数据库表结构,这就是导致数据库表数据丢失的原因。

##create-drop        加载hibernate时创建,退出是删除表结构

##update                 加载hibernate自动更新数据库结构

##validate 启动时验证表的结构,不会创建表

##none  启动时不做任何操作

#spring.jpa.hibernate.ddl-auto=validate

 

##控制台打印sql

spring.jpa.show-sql=true

 

spring.devtools.restart.enabled: true

spring.thymeleaf.cache=false

spring.thymeleaf.encoding=UTF-8

 

 

spring.http.encoding.force=true

spring.http.encoding.charset=UTF-8

spring.http.encoding.enabled=true

server.tomcat.uri-encoding=UTF-8

 

spring.mvc.date-format=yyyy-MM-dd

 

pom

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jpa</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

 

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<scope>runtime</scope>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-thymeleaf</artifactId>

</dependency>

Html

  <h1>User list</h1>

 

  <table>

    <tr>

      <th>NAME</th>

      <th>loginName</th>

      <th>nickName</th>

    </tr>

    <tr th:each="city : ${list}">

      <td th:text="${city.id}">id</td>

      <td th:text="${city.name}">loginName</td>

    </tr>

  </table>

 

  <p>

    <a href="../home.html" th:href="@{/}">Return to home</a>

  </p>

《Spring Boot 2.x》SpringDataJpa 与ThymeLeaf
SpringBoot整合

整合Servlet

注解方式

启动上添加注解

@SpringBootApplication

@ServletComponentScan

public class Springboot011Application {

 

public static void main(String[] args) {

SpringApplication.run(Springboot011Application.class, args);

}

}

Servlet类

@WebServlet(name = "myServlet",urlPatterns = "/srv",loadOnStartup = 1)

public class MyServlet extends HttpServlet {

 

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

// TODO Auto-generated method stub

System.out.println("111");

super.doGet(req, resp);

}

}

编码方式

启动类中添加

@Bean

public ServletRegistrationBean<MyServlet2> getServletRegistrationBean(){

ServletRegistrationBean<MyServlet2> bean = new ServletRegistrationBean<>(new MyServlet2(), "/s2");

bean.setLoadOnStartup(1);

return bean;

}

Servlet

无需注解

 

整合Filter

implements Filter

过滤器

同Servlet

Listener

监听器

MyListener implements ServletContextListener

同上

静态资源访问

src/main/resources/static

src/main/webapp

 

SpringBoot文件上传

指定大小

spring.http.multipart.maxFileSize=200MB

spring.http.multipart.maxRequestSize=200MB

 

spring.servlet.multipart.max-request-size = 200MB

spring.servlet.multipart.max-file-size = 200MB

表单

<form action="fileUploadController" method="post" enctype="multipart/form-data">

上传文件:<input type="file" name="filename"/><br/>

<input type="submit"/>

</form>

Controller

@RequestMapping("/fileUploadController")

public String fileUpload(MultipartFile filename) throws Exception{

System.out.println(filename.getOriginalFilename());

filename.transferTo(new File("e:/"+filename.getOriginalFilename()));

return "ok";

}

表单数据接收

   @GetMapping(value = "/hello/{id}")

    public String hello(@PathVariable("id") Integer id){

        return "ID:" + id;

}

@PostMapping(value = "/user-2")

public User saveUser2(@RequestBody User user) {

    return user;

}

 

@PostMapping(value = "/post")

public String post(@RequestParam(name = "name") String name,

                   @RequestParam(name = "age") Integer age) {

    String content = String.format("name = %s,age = %d", name, age);

    return content;

}

 

SpringData Jpa进阶使用

显示SQL

spring.jpa.show-sql=true

自定义查询

自定义接口

  1. And --- 等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd);
  2. Or --- 等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr);
  3. Between --- 等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min);
  4. LessThan --- 等价于 SQL 中的 "<",比如 findBySalaryLessThan(int max);
  5. GreaterThan --- 等价于 SQL 中的">",比如 findBySalaryGreaterThan(int min);
  6. IsNull --- 等价于 SQL 中的 "is null",比如 findByUsernameIsNull();
  7. IsNotNull --- 等价于 SQL 中的 "is not null",比如 findByUsernameIsNotNull();
  8. NotNull --- 与 IsNotNull 等价;
  9. Like --- 等价于 SQL 中的 "like",比如 findByUsernameLike(String user);
  10. NotLike --- 等价于 SQL 中的 "not like",比如 findByUsernameNotLike(String user);
  11. OrderBy --- 等价于 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user);
  12. Not --- 等价于 SQL 中的 "! =",比如 findByUsernameNot(String user);
  13. In --- 等价于 SQL 中的 "in",比如 findByUsernameIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
  14. NotIn --- 等价于 SQL 中的 "not in",比如 findByUsernameNotIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;

 

自定义SQL@Query

占位符

public interface UserDao extends Repository<AccountInfo, Long> {

 

@Query("select a from AccountInfo a where a.accountId = ?1")

public AccountInfo findByAccountId(Long accountId);

 

   @Query("select a from AccountInfo a where a.balance > ?1")

public Page<AccountInfo> findByBalanceGreaterThan(

Integer balance,Pageable pageable);

}

参数名

public interface UserDao extends Repository<AccountInfo, Long> {

 

public AccountInfo save(AccountInfo accountInfo);

 

@Query("from AccountInfo a where a.accountId = :id")

public AccountInfo findByAccountId(@Param("id")Long accountId);

 

  @Query("from AccountInfo a where a.balance > :balance")

  public Page<AccountInfo> findByBalanceGreaterThan(

@Param("balance")Integer balance,Pageable pageable);

}

 

更新

@Modifying

@Query("update AccountInfo a set a.salary = ?1 where a.salary < ?2")

public int increaseSalary(int after, int before);

直接使用Native SQL

public interface UserRepository extends JpaRepository<User, Long> {

 

  @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)

  User findByEmailAddress(String emailAddress);

}

 

Thymeleaf

编辑插件

安装地址:

<html xmlns:th="http://www.thymeleaf.org">

 

URL地址

 

在应用上下文内

1)@{userList} 相对当前路径结果为:http://localhost/thymeleaf/user/userList

 

2)@{./userList} 相对当前路径结果为:http://localhost/thymeleaf/user/userList

 

3)@{../tiger/home} 相对当前路径结果为:http://localhost/thymeleaf/tiger/home

 

4)@{/tiger/home} 相对应用根目录结果为:http://localhost/thymeleaf/tiger/home

 

5)@{https://www.baidu.com/} 绝对路径结果为:https://www.baidu.com

 

6)<link type="text/css" rel="stylesheet" th:href="@{/css/home.css}">,@ 以 "/" 开头相对应用根目录,否则是相对当

Href

 

<body>

<a th:href="@{userList(id=9527)}">1、@{userList(id=9527)}</a>

<a th:href="@{userList(id=9527,name=华安)}">2、@{userList(id=9527,name=华安)}</a>

<a th:href="@{userList(id=9527,name=${userName})}">3、@{userList(id=9527,name=${userName})}</a>

</body>

 

文本

<!--空格属于特殊字符,必须使用单引号包含整个字符串-->

<p class="css1 css2" th:class="'css1 css2'">样式</p>

 

<!--下面如果没用单引号 th:text="Big China",则页面直接报错-->

<p th:text="'Big China'">中国</p>

 

<!--后台使用:model.addAttribute("info", "Love you 中国"); 传值有空格也是没有问题的-->

<p th:text="${userName}">userName</p>

 

<!--后台传值字符串有空格是可以的,可以使用 + 进行字符串连接-->

<p th:text="'small smile'+',very good.' + ${userName}">浅浅的微笑</p>

数字计算

<p th:text="80">8</p>

<!--计算结果为 16 在进行替换-->

<p th:text="8+8">8 + 8</p>

<!--前面 8+8 计算结果为 16,然后字符串拼接上 Love,后面的 9+9也会被当做字符串拼接-->

<p th:text="8+8+' Love '+9+9">8 + 8+' Love '+9+9</p>

<!--前面 8+8 计算结果为 16,后面的 9+9因为有括号,所以也会计算结果,最后拼接 Love 字符串-->

<p th:text="8+8+' Love '+(9+9)">8 + 8+' Love '+(9+9)</p>

<!--后台传了一个:model.addAttribute("age", 35);取得结果后在进行计算-->

<p th:text="100-${age}"></p>

 

Boolean判断

<p th:text="true">布尔</p>

<!--true、false 是布尔值,and 是布尔运行符,and(与),or(或),not(非)、!(非)-->

<p th:text="true and false">true and true</p>

 

<!--后台使用 model.addAttribute("isMarry", true); 传了值-->

<!--th:if 表达式为 true,则显示标签内容,否则不显示-->

<p th:if="${isMarry}">已结婚</p>

 

<!--后台传值:model.addAttribute("age", 35);-->

<!--比较运算符:>,<,> =,<=(gtltgele)-->

<p th:if="${age}>18">已成年</p>

<p th:if="${age}<18">未成年</p>

运算

<p th:text="15 * 4">值为 60 </p>

<p th:text="15 * 4-100/10">值为 50 </p>

<p th:text="100 % 8">值为 4</p>

比较

<p th:if="5>3">5 大于 3</p>

<p th:if="5 >4">5 大于 4</p>

<p th:if="10>=8 and 7 !=8">10大于等于8,且 7 不等于 8 </p>

<p th:if="!${isMarry}">!false</p>

<p th:if="not(${isMarry})">not(false)</p>

三元运算符

<p th:text="7>5?'7大':'5大'">三元运算符</p>

<!--后台控制器输出了:model.addAttribute("age", 35);-->

<!--因为 ${xx}取值时,如果值为null,则默认整个标签不再显示-->

<p th:text="${age}!=null?${age}:'age等于 null'"></p>

<!--这里使用嵌套判断,嵌套的部分要使用括号-->

<p th:text="${age}!=null?(${age}>=18?'成年':'未成年'):'age等于 null'"></p>

<!--变量 age2 后台并没有输出,所以 age2 不存在,此时 age2 ==null-->

<p th:text="${age2}!=null?${age2}:'age2等于 null'"></p>

 

<!--后台输出了:model.addAttribute("isMarry", true);-->

<!--A>B?X:Y,这里的 Y 部分是省略的,此时如果 A>B 返回 false,则整个三元运算结果为 null-->

<p th:class="${isMarry}?'css2':'css3'">已婚</p>

 

TH标签

th:utext转义

map .addAttribute("china", "<b>Chian</b>,USA,UK");

<p th:text="${china}">默认转义</p>

<!--th:utext 不会结果进行转义-->

<p th:utext="${china}">不会转义</p>

 

th:attr 设置属性

HTML5 所有的属性,都可以使用 th:* 的形式进行设置值

<a href="http://baidu.com" th:attr="title='百度'">百度</a>

<!--设置 title、href 多个属性-->

<a href="" th:attr="title='前往百度',href='http://baidu.com'">前往百度</a>

<!--设置 href 属性-->

<a href="userList.html" th:attr="href=@{/user/userHome}">用户首页</a>

<!--设置 id 属性,data-schoolName 属性 Html 本身是没有的,但允许用户自定义 -->

<a href="#" th:attr="id='9527',data-target='user'">归海一刀</a>

 

<p th:abc="9527">th:abc="9527"</p>

 

<!--输出:<p abc123="华安">th:abc123="华安"</p>-->

<p th:abc123="华安">th:abc123="华安"</p>

Checked selected

<input type="checkbox" name="option1" checked/><span>是否已婚1?</span>

<input type="checkbox" name="option2" checked="checked"/><span>是否已婚2?</span>

---<br>

<!--后台控制器传递了一个:model.addAttribute("isMarry", true);-->

<!--option3、option4 会选中;option5 不会选中-->

<input type="checkbox" name="option3" th:checked="${isMarry}"/><span>是否已婚3?</span>

<input type="radio" name="option4" th:checked="${isMarry}"/><span>是否本科?</span>

<input type="radio" name="option5" th:checked="!${isMarry}"/><span>是否应届生?</span>

---------------------

<select>

<option>a</option>

<option th:selected="${isMarry}">已婚</option>

<option  th:selected="${!isMarry}">未婚</option>

 

</select>

<input type="text" th:autofocus="false">

<input type="text" th:autofocus="true">

<input type="text" th:autofocus="false">

 

日期格式化

 

    <span th:text="${#dates.format(date, 'yyyy-MM-dd HH:mm')}"></span>

循环

JSTL 有一个 <c:foreach>,同理 Thymeleaf 也有一个 th:each。作用都是一样的,都是用于遍历数组、List、Set、Map 等数据。

在Select上循环

    <option th:each="city : ${list}" th:text="${city.name}" th:selected="${cityName} eq ${city.name}">横岗</option>

  

状态变量loopStatus

如果不指定 为变量+Stat

  1. index: 当前迭代对象的index(从0开始计算)   
  2. count:  当前迭代对象的index(从1开始计算)   
  3. size: 被迭代对象的大小     current:当前迭代变量   
  4. even/odd: 布尔值,当前循环是否是偶数/奇数(从0开始计算)   
  5. first: 布尔值,当前循环是否是第一个   
  6. last: 布尔值,当前循环是否是最后一个

<tr th:each="city,status : ${list}" th:style="${status.odd}?'background-color:#c2c2c2'">

<!-- EL JSTL-->

<td th:text = "${status.count}"></td>

<td th:text = "${city.id}"></td>

<td th:text = "${city.name}"></td>

</tr>

If/else

<p th:if="${isMarry}">已婚1</p>

<p th:unless="${isMarry}">未婚</p>

Switch/case 多条件判断

<div th:switch="1">

    <p th:case="0">管理员</p>

    <p th:case="1">操作员</p>

    <p th:case="*">未知用户</p>

</div>

 

<!--数字类型:当没有 case 匹配时,取默认值,当有多个匹配,只取第一个-->

<div th:switch="-1">

    <p th:case="0">管理员</p>

    <p th:case="*">操作员</p>

    <p th:case="*">未知用户</p>

</div>

 

<!--布尔类型,多个case满足时,只取第一个-->

<div th:switch="${isMarry}">

    <p th:case="true">已婚</p>

    <p th:case="true">已成年</p>

    <p th:case="false">未婚</p>

</div>

 

<!--字符串类型-->

<div th:switch="'For China'">

    <p th:case="'For USA'">美国</p>

    <p th:case="'For UK'">英国</p>

    <p th:case="'For China'">中国</p>

    <p th:case="*">未知国籍</p>

</div>

内联表达式

[[...]] 等价于 th:text(结果将被 HTML 转义),[(...)] 等价于 th:utext(结果不会执HTML转义)

<p>[[${china}]]</p>

<p>[(${china})]</p>

<p>[[Lo1ve]]</p>

<p>[['I Love You Baby']]</p>

<p>[(9527)]</p>

th:inline =“none” 来禁联。

内联 JavaScript

<script type="text/javascript" th:inline="javascript">

     var info = [[${info}]];

        var age = [[${age}]];

        var id = [[${id}]];

        var name = [[${name}]];

        console.log(id, name, age, info);

        </script>

前后端分离

   <script type="text/javascript" th:inline="javascript">

        /**

         * Thymeleaf 将自动忽略掉注释之后 和 分号之前的所有内容,如下为 "前端测试"

         */

        var info = /*[[${info}]]*/ "前端测试";

        console.log(info);

</script>

对象属性

URL

<p>${param.size()}=[[${param.size()}]]</p>

<!--/*判断请求参数是否为空*/-->

<p>${param.isEmpty()}=[[${param.isEmpty()}]]</p>

<!--获取某个参数值,不存在时为null-->

<p>${param.u_id}=[[${param.u_id}]]</p>

Session

<p>${session.size()}=[[${session.size()}]]</p>

<!--/*判断请求参数是否为空*/-->

<p>${session.isEmpty()}=[[${session.isEmpty()}]]</p>

<!--获取某个参数值,不存在时为null-->

<p>${session.user.id}=[[${session.user.id}]]</p>

完整文档

https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#base-objects

mybatis

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

配置文件

MybatisConfig.xml

SSM中需要配置

  • 数据url

  • 数据库连接池

  • 映射文件

  • 事务

在SpringBoot中整合到property中了

Mapper.xml

namespace

接口绑定 和接口

就可以不用写DAO实现类,Mybatis会通过绑定自动找到要执行的sql语句。

resultMap

结果集对应到实体类的字段到属性映射

xml 方式

传统方式

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">  
  
<!-- version: $Id$ -->  
<configuration>  
    <!-- 引用JDBC属性的配置文件 -->  
    <properties resource="database.properties" />  
  
    <environments default="development">  
        <environment id="development">  
            <!-- 使用JDBC的事务管理 -->  
            <transactionManager type="JDBC" />  
            <!-- POOLED :JDBC连接对象的数据源连接池的实现,不直接支持第三方数据库连接池 -->  
            <dataSource type="POOLED">  
                <property name="driver" value="${database.driver}" />  
                <property name="url" value="${database.url}" />  
                <property name="username" value="${database.username}" />  
                <property name="password" value="${database.password}" />  
            </dataSource>  
        </environment>  
  
    </environments>  
  
    <!-- ORM映射文件 -->  
    <mappers>  
        <!-- 注解的方式 -->  
        <mapper class="com.iflytek.dao.mapper.AccountMapper" />  
        <!-- XML的方式 -->  
        <mapper resource="com/mashibing/dao/xml/AccountMapper.xml" />  
        <!-- 这里对于注解,还可以通过<package name="com.mashibing.dao.mapper"/> -->  
    </mappers>  
</configuration>  

Service 配置

public class AccountService {  
​
    public boolean insertAccount(Account account) {  
        boolean flag = false;  
        SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession();  
        try {  
            accountMapper accountMapper = sqlSession.getMapper(AccountMapper.class);  
            int result = accountMapper.insert(student);  
            if (result > 0) {  
                flag = true;  
            }  
            sqlSession.commit();  
        } finally {  
            sqlSession.close();  
        }  
        return flag;  
    }  
  
​
    public Student getAccountById(int id) {  
        SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession();  
        try {  
            AccountMapper AccountMapper = sqlSession.getMapper(AccountMapper.class);  
            return AccountMapper.selectByPrimaryKey(id);  
        } finally {  
            sqlSession.close();  
        }  
    }  
  
​
    public List<Student> getAllStudents() {  
        SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession();  
        try {  
            StudentMapper StudentMapper = sqlSession.getMapper(StudentMapper.class);  
            return StudentMapper.selectByExample(new StudentExample());  
        } finally {  
            sqlSession.close();  
        }  
    }  
  
​
    public boolean updateAccount(Account account) {  
        SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession();  
        boolean flag = false;  
        try {  
            AccountMapper AccountMapper = sqlSession.getMapper(AccountMapper.class);  
            int result = AccountMapper.updateByPrimaryKey(Account);  
            if (result > 0) {  
                flag = true;  
            }  
            sqlSession.commit();  
        } finally {  
            sqlSession.close();  
        }  
        return flag;  
  
    }  
  
 
    public boolean deleteAccount(int id) {  
        SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession();  
        boolean flag = false;  
        try {  
            AccountMapper AccountMapper = sqlSession.getMapper(AccountMapper.class);  
            int result = AccountMapper.deleteByPrimaryKey(id);  
            if (result > 0) {  
                flag = true;  
            }  
            sqlSession.commit();  
        } finally {  
            sqlSession.close();  
        }  
        return flag;  
    }  
  
}  

 

 

 

与SpringBoot整合

引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springboot03-mybatis</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot03-mybatis</name>
    <description>Demo project for Spring Boot</description>
​
    <properties>
        <java.version>1.8</java.version>
    </properties>
​
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.1</version>
        </dependency>
​
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        
    </dependencies>
​
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
​
</project>
​

 

mapper

<?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.mashibing.springboot.mapper.AccountMapper">
   
   <resultMap type="com.mashibing.springboot.mapper.Account" id="BaseResultMap">
   
    <result column="login_name" property="loginName"/>
    <result column="password" property="password"/>
   
   </resultMap>
   
   
    <insert id="save" parameterType="Account">
        INSERT INTO account(login_name,password)
        VALUES
        (
        #{loginName},#{password}
        )
    </insert>
    
    <select id="findAll" resultMap="BaseResultMap">
        select * from account
    </select>
    
</mapper>
​
​
​

application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
##数据库用户名
spring.datasource.username=root
##数据库密码
spring.datasource.password=840416
​
# 用来实例化mapper接口
mybatis.type-aliases-package=com.mashibing.springboot.mapper
# 对应的sql映射
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

AccountMapper

package com.mashibing.springboot.mapper;
​
import org.apache.ibatis.annotations.Mapper;
​
@Mapper
public interface AccountMapper {
​
    void save(Account account);
}
​
​

Account

​
public class Account {
    private int id;
    private String loginName;
    private String password;
    private String nickName;
    private int age;
    private String location;
    private int banlance;
    public int getId() {
​

 

显示日志

logging.level.com.mashibing.springboot.mapper=debug

 

注解查询

    @Select("select * from account1")
    List<Account> findAll();
​

 

 

查找mapper接口

在入口加入 MapperScan

@MapperScan("com.mashibing.springboot.mapper") public class Springboot03MybatisApplication {

每一个mapper接口上加入

@Mapper public interface AccountMapper {

Mapper 自动生成

eclipse插件 市场搜素

MyBatis Generator

图形化

https://github.com/zouzg/mybatis-generator-gui

分页查询

 

依赖

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.12</version>
</dependency>
​

Service

    public Object findPage(int pageNum, int pageSize) {
​
        PageHelper.startPage(pageNum, pageSize);
        AccountExample example = new AccountExample();
        return mapper.selectByExample(example );
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值