Spring全家桶之SpringBoot——初级阶段

时间:2022-07-22
本文章向大家介绍Spring全家桶之SpringBoot——初级阶段,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、介绍

简介

• Spring Boot 设计目的是用来简化新Spring 应用的初始搭建以及开发过程。 • 嵌入的Tomcat,无需部署WAR 文件 • Spring Boot 并不是对Spring 功能上的增强,而是提供了一种快速使用Spring 的方式。

学习导图

二、构建Spring Boot 项目及启动器讲解

编写HelloWorld程序

1.使用maven 构建SpringBoot 项目

选择的是jar项目 需要在创建时手动添加SpringBoot父项目 本博文所有演示案例都是基于本步骤,故在下面不做重复讲解,如果有变会特别贴出

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.10.RELEASE</version>
  </parent>

2. 注入SpringBoot启动器坐标

 <!-- springBoot的启动器 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

注意 使用SpringBoot 1.5.10需要Jdk 1.7及以上 ,如果没有达到需要手动配置jdk版本 ,代码如下

<!-- 修改jdk版本 -->
  <properties>
  	<java.version>1.7</java.version>
  </properties>
<dependencies>

3 .编写返回HelloWorld的Controller

package ah.szxy.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloWorld {
	
	@RequestMapping("/helloworld")
	@ResponseBody
	public Map<String,Object> showPage() {
		Map<String, Object>map=new HashMap<String, Object>();
		map.put("msg", "helloWorld");
		
		return map;
	}
}

4. 编写启动器代码

@SpringBootApplication 表示当前项目是一个SpringBoot项目

package ah.szxy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
 * SpringBoot 启动器
 * @author chy
 *
 */
@SpringBootApplication
public class Client {
	public static void main(String[] args) {
		SpringApplication.run(Client.class, args);
	}
}

5. 运行结果

右击启动器 ,Run as JavaApplication 访问 ; http://localhost:8080/helloworld

补充 : 编写启动器需要注意的问题

启动器所在位置必须和controller 位于同一级包下(如下图),或者位于controller 的上一级包中,但是不能放到controller 子包下以及其他包,如Dao包或者Serrvice包。

常用的SpringBoot启动器

启动器名称

作用

spring-boot-starter-web

支持全栈式的web 开发,包括了romcat 和springMVC 等jar

spring-boot-starter-jdbc

支持spring 以jdbc 方式操作数据库的jar 包的集合

spring-boot-starter-redis

支持redis 键值存储的数据库操作

spring-boot-starter-test

SpringBoot支持单元集成测试的启动器

spring-boot-starter-thymeleaf

SpringBoot的支持 thymeleaf 语法(类似el表达式 )的启动器

spring-boot-starter-cache

Spring Boot 缓存支持启动器

二、SpringBoot整合Servlet

1.使用maven 构建SpringBoot 项目

同上

2. 注入SpringBoot启动器坐标

同上

3. 方式一

常规方式 ,通过注解注入Servlet的name与访问路径 ,然后启动器如以往一样

创建Servlet @WebServlet(name=“FirstServlet”,urlPatterns="/first") 相当于在web.xml中创建了servlet的name以及访问路径

package ah.szxy.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 *SpringBoot整合Servlet方式一
 *@WebServlet(name="FirstServlet",urlPatterns="/first")相当于如下:
 *
 *<servlet>
 *	<servlet-name>FirstServlet</servlet-name>
 *	<servlet-class>ah.szxy.servlet.FirstServlet</servlet-class>
 *</servlet>
 *<servlet-mapping>
 * <servlet-name>FirstServlet</servlet-name>
 * <url-pattern>/first</url-pattern>
 *</servlet-mapping>
 *
 */

@WebServlet(name="FirstServlet",urlPatterns="/first")
public class FirstServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("FirstServlet............");
	}
}

创建启动器类 @SpringBootApplication 表示该程序时SpringBoot启动程序 @ServletComponentScan 表示 在springBoot启动时会扫描@WebServlet,并将该类实例化

package ah.szxy;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

/**
 * SpringBoot整合Servlet方式一
 *
 *
 */
@SpringBootApplication
@ServletComponentScan //在springBoot启动时会扫描@WebServlet,并将该类实例化
public class Client {

	public static void main(String[] args) {
		SpringApplication.run(Client.class, args);
	}

}

运行结果 访问 http://localhost:8080/first

4. 方式二

servlet代码如同javaEE时一样 ,但是启动器创建了一个获取Servlet注册的Bean的方法 , 通过@bean 标签,相当于在配置文件中配置了servlet的访问路径

创建Servlet

/**
 *SpringBoot整合Servlet方式二
 *
 */

public class SecondServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("SecondServlet..........");
	}
	
}

创建启动器类 @bean 标签,相当于在配置文件中配置了servlet的访问路径

/**
 * SpringBoot整合Servlet方式二
 *
 *
 */
@SpringBootApplication
public class Client2 {

	public static void main(String[] args) {
		SpringApplication.run(Client2.class, args);
	}
	
	@Bean
	public ServletRegistrationBean getServletRegistrationBean(){
		ServletRegistrationBean bean = new ServletRegistrationBean(new SecondServlet());
		bean.addUrlMappings("/second");
		return bean;
	}
}

运行结果 访问 :http://localhost:8080/second

这两种方法实现的功能都是一样的, 但是我们在实际开发中都比较推荐使用注解的方式, 后面的过滤器 以及监听器亦是如此 . 方法二太累赘,基本没人用了。而在学习中使用方法二其实是为了让大家更好的理解框架

三、SpringBoot整合Filter

本项目是基于上一个项目 ,两个Servlet程序不变 ,在此基础上添加了两个过滤器

方式一

创建Filter @WebFilter(filterName=“FirstFilter”,urlPatterns="/first") ,表示在web.xml注册Filter ,过滤器名字为FirstFilter ,拦截的url是 /first

package ah.szxy.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
/**
 * SpringBoot整合Filter方式一
 * @author chy
 *
 */
@WebFilter(filterName="FirstFilter",urlPatterns="/first")
public class FirstFilter implements Filter{

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
			throws IOException, ServletException {

		System.out.println("进入过滤器");
		arg2.doFilter(arg0, arg1);
		System.out.println("离开过滤器");
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
		
	}

}

创建启动类

package ah.szxy;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

/**
 * SpringBoot整合Servlet方式一
 *
 *
 */
@SpringBootApplication
@ServletComponentScan //在springBoot启动时会扫描@WebServlet,并将该类实例化
public class Client {

	public static void main(String[] args) {
		SpringApplication.run(Client.class, args);
	}

}

运行结果

方式二

创建Filter

public class SecondFilter implements Filter{

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
			throws IOException, ServletException {
		System.out.println("进入Filter");
		arg2.doFilter(arg0, arg1);
		System.out.println("离开Filter");
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
		
	}

}

创建启动类 通过@Bean注册filter

@SpringBootApplication
public class Client2 {

	public static void main(String[] args) {
		SpringApplication.run(Client2.class, args);
	}

	@Bean
	public ServletRegistrationBean getServletRegistrationBean() {
		ServletRegistrationBean bean = new ServletRegistrationBean(new SecondServlet());
		bean.addUrlMappings("/second");
		return bean;
	}

	/**
	 * 注册Filter
	 */
	@Bean
	public FilterRegistrationBean getFilterRegistrationBean() {
		FilterRegistrationBean bean = new FilterRegistrationBean(new SecondFilter());
		// bean.addUrlPatterns(new String[]{"*.do","*.jsp"});//拦截多个时
		bean.addUrlPatterns("/second");
		return bean;
	}

}

运行结果

四、SpringBoot整合Listener

方式一

创建Filter

package ah.szxy.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* springBoot 整合Listener 
* @WebListener 自动注册,相当于在web.xml中添加如下代码
*
*<listener>
* <listener-class>ah.szxy.listener.FirstListener</listener-class>
*</listener>
*/
@WebListener
public class FirstListener implements ServletContextListener{

	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		// TODO Auto-generated method stub
		System.out.println("FirstListener.contextDestroyed(上下文监听器)");
	}

	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		// TODO Auto-generated method stub
		System.out.println("FirstListener.contextInitialized(上下文监听器)");
	}

}

创建启动类 @ServletComponentScan 在springBoot启动时会扫描@WebServlet,并将该类实例化 没有Servlet或没有Servlet使用@WebServlet 就不需要使用@ServletComponentScan注解

package ah.szxy;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;


@SpringBootApplication
public class Client {

	public static void main(String[] args) {
		SpringApplication.run(Client.class, args);
	}

}

运行结果

方式二

创建Filter

package ah.szxy.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class SecondListener implements ServletContextListener{

	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		// TODO Auto-generated method stub
		System.out.println("SecondListener.contextDestroyed(上下文监听器)");
	}

	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		// TODO Auto-generated method stub
		System.out.println("SecondListener.contextInitialized(上下文监听器)");
	}
	}

创建启动类

@SpringBootApplication
public class Client2 {

	public static void main(String[] args) {
		SpringApplication.run(Client2.class, args);
	}

	/**
	 * 注册listener
	 */
	@Bean
	public ServletListenerRegistrationBean<SecondListener> getServletListenerRegistrationBean() {
		ServletListenerRegistrationBean<SecondListener> bean = new ServletListenerRegistrationBean<SecondListener>(
				new SecondListener());
		return bean;
	}

}

运行结果

五 、访问静态资源

1. SpringBoot 从classpath/static 的目录访问静态资源

注意目录名称必须是static

启动类

@SpringBootApplication
public class Client {

	public static void main(String[] args) {
		SpringApplication.run(Client.class, args);
	}

}

访问 http://localhost:8080/images/1.png

2. webapp 根目录下

需要将 src 创建webapp目录 ,在src目录创建静态资源 建议使用这一种方式进行静态资源的存放 ,方便后面的文件上传以及对视图层的整合

index.html

  <body>
    <h1>静态资源访问方式一</h1><hr>
    <img alt="" src="images/2.png">
  </body>

访问 http://localhost:8080/

六、文件上传

1. 编写启动类

@SpringBootApplication
public class Client {

	public static void main(String[] args) {
		SpringApplication.run(Client.class, args);
	}

}

2. 用于随机生成不重复的图片名的工具类

package ah.szxy.util;

import java.util.Random;
import java.util.UUID;

/**
 * 各种id生成策略
 * @version 1.0
 */
public class IDUtils {

	/**
	 * 图片名生成
	 */
	public static String genImageName() {
		//取当前时间的长整形值包含毫秒
		long millis = System.currentTimeMillis();
		//long millis = System.nanoTime();
		//加上三位随机数
		Random random = new Random();
		int end3 = random.nextInt(1000);
		//如果不足三位前面补0
		String str = millis + String.format("%03d", end3);
		return str;
	}
	
	/**
	 * 商品id生成
	 */
	public static long genItemId() {
		//取当前时间的长整形值包含毫秒
		long millis = System.currentTimeMillis();
		//long millis = System.nanoTime();
		//加上两位随机数
		Random random = new Random();
		int end2 = random.nextInt(99);
		//如果不足两位前面补0
		String str = millis + String.format("%02d", end2);
		long id = new Long(str);
		return id;
	}
	
	public static void main(String[] args) {
		for(int i=0;i< 100;i++)
		System.out.println(genItemId());
	}
}

3 .配置文件上传属性的配置文件

application.properties 文件上传大小默认是10MB ,需要手动对上传大小进行修改

spring.http.multipart.maxFileSize=200MB
spring.http.multipart.maxRequestSize=200MB

属性

作用

设置单个上传文件的大小

spring.http.multipart.maxFileSize

设置一次请求上传文件的总容量

spring.http.multipart.maxRequestSize

4. 编写controller

需要在webapp目录下 ,创建一个images的文件夹

package ah.szxy.controller;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import ah.szxy.util.IDUtils;

/**
 * SpringBoot 文件上传
 *
 *
 */
@RestController // 表示该类下的方法的返回值会自动做json 格式的转换
public class FileUpLoadController {

	/**
	 * 处理文件上传___上传到本地
	 */
	@RequestMapping("/fileUpLoad")
	public Map<String, Object> fileUpload(MultipartFile file) throws Exception {
		System.out.println(file.getOriginalFilename());
		//放在e盘下
		file.transferTo(new File("e:/" + file.getOriginalFilename()));
		Map<String, Object> map = new HashMap<>();
		map.put("msg", "ok");
		return map;
	}
	
	/**
	 * 处理文件上传___上传到本项目images目录下
	 */
	@RequestMapping("/fileUpLoadToProject")
	public String fileUpLoadToProject(MultipartFile file,HttpSession session) {
		
				//通过session获取绝对路径,方法内部加上/WEB-INF/images,表示在项目的images目录下,需要创建该文件夹并进行静态资源放行
				String path=session.getServletContext().getRealPath("/images");
				String fileName = file.getOriginalFilename();//这个就是文件的路径
				File file2 = new File(path, fileName );
				try {
					file.transferTo(file2);
				} catch (IllegalStateException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}		

				//将文件的路径放到类属性中,修改此处
			    //goods.setPicture(fileName);
				System.out.println(fileName);
				return "ok";
		}
	
	
	/**
	 * 处理文件上传___上传到本项目images目录下,且名字随机
	 */
	@RequestMapping("/fileUpLoadToProjectAndNameRandom")
	public String fileUpLoadToProjectAndNameRandom(MultipartFile file, HttpSession session) {
		boolean flag=false;//上传结果
		String filename=null;//上传后文件的名称
		
		
		try {
			filename=IDUtils.genImageName();
			//原始文件名
			String originalFilename = file.getOriginalFilename();
			String ext = originalFilename.substring(originalFilename.lastIndexOf("."));//.之前的去掉
			filename=filename+ext;
			System.out.println("filename"+filename);
			//通过工具类上图片
			String path=session.getServletContext().getRealPath("/images");
			File fileName = new File(path, filename );
			try {
				file.transferTo(fileName);
				flag=true;
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}		

			
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (flag) {
			System.out.println("ok");
		}else {
			System.out.println("false");
		}	
		return "ok";
	}
}

5. 前台页面

注意 表单提交的方式为 : post enctype的值为 : multipart/form-data file类型的输入框的name属性要和 MultipartFile 的形参一样 ,这样才能进行文件的上传

  <body>
    <h1>文件上传到本地e盘</h1><hr>
   	<form action="/fileUpLoad" method="post" enctype="multipart/form-data">
   		<input type="file" name="file" ><br>
   		<input type="submit" value="点击上传">
   	</form>	

   	 <h1>文件上传到本项目</h1><hr>
   	<form action="/fileUpLoadToProject" method="post" enctype="multipart/form-data">
   		<input type="file" name="file" ><br>
   		<input type="submit" value="点击上传">
   	</form>	
   	
   	
   	 <h1>文件上传到本项目名字随机</h1><hr>
   	<form action="/fileUpLoadToProjectAndNameRandom" method="post" enctype="multipart/form-data">
   		<input type="file" name="file" ><br>
   		<input type="submit" value="点击上传">
   	</form>	
  </body>

Spring Boot 第三章(视图层技术)

七、Spring Boot 整合视图层技术

SpringBoot整合Jsp技术

需要自己创建相关文件夹, 诸如 jsp 文件夹等

1. 创建项目

父项目

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.10.RELEASE</version>
  </parent>

2. 额外添加相关坐标

因为SpringBoot不是特别支持Jsp ,所以要使用时需要加上额外添加相关的坐标支持

<dependencies>
		<!-- springBoot 的启动器 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- jstl -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>
		<!-- jasper:SpringBoot对jsp的支持 -->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>
	</dependencies>

3. 创建springBoot 的全局配置文件,application.properties

作用类似视图解析器

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

4. 创建Controller

/**
 * SpringBoot整合Jsp
 * @author chy
 *
 */
@Controller // 之所以不要@RestController是因为要进行页面的跳转而不是发送json格式字符串
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";
		}
}

5. 创建jsp

使用 jstl 需要在 jsp页面开始加入jstl 核心标签库

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<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>

6. 启动类

@SpringBootApplication
public class App {
	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}

}

SpringBoot 整合Freemarker

1. 创建项目

父项目
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.10.RELEASE</version>
  </parent>

2. 修改pom.xml ,添加坐标

<dependencies>
		<!-- springBoot 的启动器 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- freemarker 启动器的坐标 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-freemarker</artifactId>
		</dependency>
	</dependencies>

3. 编写视图代码

建议使用HBuilder编写改代码 ,方式如下

打开目录 ,在java工作空间找到该项目

注意: springBoot 要求模板形式的视图层技术的文件必须要放到src/main/resources 目录下必须要一个名称为templates

视图层代码 userList.ftl

<html>

	<head>
		<title>展示用户数据</title>
		<meta charset="utf-9"></meta>
	</head>

	<body>
		<table border="1" align="center" width="50%">
			<tr>
				<th>ID</th>
				<th>Name</th>
				<th>Age</th>
			</tr>
			<#list list as user>
				<tr>
					<td>${user.userid}</td>
					<td>${user.username}</td>
					<td>${user.userage}</td>
				</tr>
			</#list>
		</table>
	</body>
</html>

4. 创建Controller

@Controller // 之所以不要@RestController是因为要进行页面的跳转而不是发送json格式字符串
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";
		}
}

5. 创建启动类

@SpringBootApplication
public class App {
	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}

}

运行结果

SpringBoot 整合Thymeleaf

1. 创建项目

父项目
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.10.RELEASE</version>
  </parent>

2. 修改pom.xml ,添加坐标

<!-- 对thymeleaf进行优化,使其对html文件的格式不做严格要求 , 降低开发难度-->
	<properties>
		<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
		<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>
	</properties>

	<dependencies>
		<!-- springBoot 的启动器 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- springBoot 的启动器 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
	</dependencies>

不能直接访问视图层html页面,只能通过controller来跳转到对应的页面!!! 如果想直接访问页面需要添加一个页面访问的Controller

@Controller
public class PageController {
	
	@RequestMapping("/{page}")
	public String showPage(@PathVariable String page) {
		
		return page;
		
	}
}

3. 编写视图代码

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Thymeleaf 入门</title>
</head>
<body>
	<span th:text="Hello"></span>
	<hr />
	<span th:text="${msg}"></span>
</body>
</html>

4. 创建Controller

@Controller
public class ThymeleafController {
	@RequestMapping("/showPage")
	public String showInfo(Model model) {
		
		model.addAttribute("msg", "Thymeleaf的入门案例");
		return "index";
	}
}

5. 创建启动类

/**
 * 启动Thymeleaf入门案例
 * @author chy
 *
 */
@SpringBootApplication
public class App {
	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}
}

测试结果

Thymeleaf 语法详解

变量输出与字符串操作

语法

作用

th:value

在页面中输出值

th:value

可以将一个值放入到input 标签的value 中

Thymeleaf 内置对象

注意语法: 1,调用内置对象一定要用# 2,大部分的内置对象都以s 结尾strings、numbers、dates

语法

作用

${#strings.isEmpty(key)}

判断字符串是否为空,如果为空返回true,否则返回false

${#strings.contains(msg,‘T’)}

判断字符串是否包含指定的子串,如果包含返回true,否则返回false

${#strings.startsWith(msg,‘a’)}

判断当前字符串是否以子串开头,如果是返回true,否则返回false

${#strings.endsWith(msg,‘a’)}

判断当前字符串是否以子串结尾,如果是返回true,否则返回false

${#strings.length(msg)}

返回字符串的长度

${#strings.indexOf(msg,‘h’)}

查找子串的位置,并返回该子串的下标,如果没找到则返回-1

${#strings.substring(msg,13)} ${#strings.substring(msg,13,15)}

截取子串,用户与jdk String 类下SubString 方法相同

${#strings.toUpperCase(msg)} ${#strings.toLowerCase(msg)}

字符串转大小写。

日期格式化处理

语法

作用

${#dates.format(key)}

格式化日期,默认的以浏览器默认语言为格式化标准

${#dates.format(key,‘yyy/MM/dd’)}

按照自定义的格式做日期转换

${#dates.year(key)} ${#dates.month(key)} ${#dates.day(key)}

获取具体的年月日信息year:取年 Month:取月Day:取日

条件判断

if语句__th:if

<span th:if="${sex} == '男'">
性别:男
</span>
<span th:if="${sex} == '女'">
性别:女
</span>

switch语句__th:switch

<span th:switch="${id}">
		<span th:case="1">ID为1</span>
		<span th:case="2">ID为2</span>
		<span th:case="3">ID为3</span>
	</span>

迭代遍历

遍历List集合+状态变量
@RequestMapping("/show2")
	public String showOther2(Model model) {
		List<Users> list=new ArrayList<Users>();
		list.add(new Users(1, "秦小敏", 16));
		list.add(new Users(2, "沙小光", 17));
		list.add(new Users(3, "超叔", 18));
		
		model.addAttribute("list", list);
		return "index3";
	}
<table border="1">
		<tr>
			<th>ID</th>
			<th>Name</th>
			<th>Age</th>
			<th>Index</th>
			<th>Count</th>
			<th>Size</th>
			<th>Even</th>
			<th>Odd</th>
			<th>First</th>
			<th>lase</th>
		</tr>
		<tr th:each="u,var : ${list}">
			<td th:text="${u.userid}"></td>
			<td th:text="${u.username}"></td>
			<td th:text="${u.userage}"></td>
			<td th:text="${var.index}"></td>
			<td th:text="${var.count}"></td>
			<td th:text="${var.size}"></td>
			<td th:text="${var.even}"></td>
			<td th:text="${var.odd}"></td>
			<td th:text="${var.first}"></td>
			<td th:text="${var.last}"></td>
		</tr>
	</table>

状态变量属性

状态变量

作用

index

当前迭代器的索引从0 开始

count

:当前迭代对象的计数从1 开始

size

:被迭代对象的长度

even/odd

布尔值,当前循环是否是偶数/奇数从0 开始

first

布尔值 ,当前循环的是否是第一条,如果是返回true 否则返回false

last

布尔值,当前循环的是否是最后一条,如果是则返回true 否则返回false

遍历map集合
@RequestMapping("/show3")
	public String showOther3(Model model) {
		Map<String, Users>map=new HashMap<String, Users>();
		map.put("u1", new Users(1, "秦小敏", 16));
		map.put("u2", new Users(2, "沙小光", 17));
		map.put("u3", new Users(3, "超叔", 18));
		model.addAttribute("map", map);
		return "index4";
	}
<table border="1" align="center">
		<tr>
			<th>ID</th>
			<th>Name</th>
			<th>Age</th>
		</tr>
		<tr th:each="maps:${map}">
			<td th:each="entry:${maps}" th:text="${entry.value.userid}"></td>
			<td th:each="entry:${maps}" th:text="${entry.value.username}"></td>
			<td th:each="entry:${maps}" th:text="${entry.value.userage}"></td>
		</tr>
	</table>

域对象操作

	@RequestMapping("/show4")
	public String showOther4(HttpServletRequest req,Model model) {
		req.setAttribute("req", "HttpServletRequest");//request对象
		req.getSession().setAttribute("sess", "sesssion");//session对象
		return "index5";
	}
body>
<!-- 获取request作用域对象 -->
	<span th:text="${#httpServletRequest.getAttribute('req')}"></span><br>
<!-- 获取session对象 -->
	<span th:text="${session.sess}"></span>
</body>

URL表达式

分类 th:href th:src

url 表达式语法 基本语法:@{}

@Controller
public class ThymeleafController {
	@RequestMapping("/{page}")
	public String showPage(@PathVariable String page,Integer id) {
		System.out.println(id);
		return page;
	}
<body>
<!-- 绝对路径 ,跳转到b站 -->
	<a href="http://www.bilibili.com">绝对路径</a><br>
	<a th:href="@{http://www.bilibili.com}">Thymeaf绝对路径</a>
	<br>
<!-- 相对路径 ,跳转到名为 show.html的页面 -->
	<a th:href="@{/show}">相对路径</a><br>
<!-- 相当于在tomcat的根目录下查找 -->
	<a th:href="@{~/project2/resourcename}">相对于服务器的根</a><br>
	
<!-- 在url 中实现参数传递 -->
	<a th:href="@{/show(id=1,name=zhagnsan)}">相对路径-传参</a><br>
<!-- 在url 中通过restful 风格进行参数传递  -->
	<a th:href="@{/path/{id}/show(id=1,name=zhagnsan)}"> 相对路径- 传参-restful</a>
</body>

八、SpringBoot 整合SpringMVC+MyBatis

1. 搭建项目环境

创建项目时 ,需要继承SpringBoot启动器的父类 (可以在下面pom文件中找) ,选择maven 的jar项目

修改pom文件

<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>1.5.10.RELEASE</version>
	</parent>
	<groupId>ah.szxy.SpringBoot</groupId>
	<artifactId>12-SpringBoot-SpringMVC-Mybatis</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<!-- 对thymeleaf进行优化,使其对html文件的格式不做严格要求 , 降低开发难度 -->
	<properties>
		<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
		<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>
	</properties>

	<dependencies>
		<!-- springBoot 的启动器 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- springBoot 的启动器 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<!-- Mybatis 启动器 -->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.1.1</version>
		</dependency>
		<!-- mysql 数据库驱动 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<!-- druid 数据库连接池 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.0.9</version>
		</dependency>
	</dependencies>
</project>

添加application.properties 全局配置文件

在resource目录下

spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ssm
spring.datasource.username=root
spring.datasource.password=root

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

mybatis.type-aliases-package=ah.szxy.pojo

数据库表设计

CREATE TABLE `users` (
  `userid` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(30) DEFAULT NULL,
  `userage` int(11) DEFAULT NULL,
  PRIMARY KEY (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

2. 具体功能实现

创建实体类

package ah.szxy.pojo;

public class Users {
	private int userid;
	private String username;
	private int userage;
//取值赋值方法以及带参无参构造方法自行添加
}

创建mapper 接口以及映射配置文件

public interface UsersMapper {
	/**
	 * 添加用户
	 * @param users
	 */
	void insertUser(Users users);
	/**
	 * 查询所有用户
	 * @return
	 */
	List<Users> findAllUser();
	/**
	 * 通过id查询用户
	 * @param userid
	 */
	Users findUserById(Integer userid);
	/**
	 * 更新
	 * @param users
	 */
	void updateUser(Users users);
	/**
	 * 删除
	 * @param userid
	 */
	void deleteUser(Integer userid);
}
<?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="ah.szxy.mapper.UsersMapper">
	<insert id="insertUser" parameterType="users">
		insert into users(username,userage) values(#{username},#{userage})
	</insert>
	
	<select id="findAllUser" resultType="users">
		select * from users
	</select>
	<select id="findUserById" resultType="users">
		select * from users where userid=#{userid}
	</select>
	<update id="updateUser" parameterType="users">
		update users set username=#{username},userage=#{userage} where userid=#{userid}	
	</update>
	<delete id="deleteUser" parameterType="users">
		delete from users where userid=#{userid}
	</delete>
</mapper>

创建业务层

public interface UsersService {
	void insertUser(Users users);
	List<Users> findAllUser();
	Users findUserById(Integer userid);
	void updateUser(Users users);
	void deleteUser(Integer userid);
}
@Service
public class UsersServiceImpl implements UsersService{
	@Autowired
	private UsersMapper usersMapper;
	
	@Override
	public void insertUser(Users users) {
		this.usersMapper.insertUser(users);
	}

	@Override
	public List<Users> findAllUser() {

		return this.usersMapper.findAllUser();
	}

	@Override
	public Users findUserById(Integer userid) {

		return this.usersMapper.findUserById(userid);
	}

	@Override
	public void updateUser(Users users) {

		this.usersMapper.updateUser(users);
	}

	@Override
	public void deleteUser(Integer userid) {
		this.usersMapper.deleteUser(userid);
	}

}

创建Controller

页面跳转Controller

@Controller
public class PageController {
	
	
	@RequestMapping("/{page}")
	public String showPage(@PathVariable String page) {
		
		return page;
	}
}

具体业务功能实现的Controller 注意 :如果需要从Controller中的一个方法跳转到另一个方法 ,则和SpringMVC一样, 列如 return "redirect:findAll";

@Controller
@RequestMapping("/user")
public class UsersController {
	
	@Autowired
	private UsersService usersService;
	
	@RequestMapping("/add")
	public String addUser(Users users) {
		
		this.usersService.insertUser(users);
		return "ok";
	}
	
	@RequestMapping("/findAll")
	public String findAllUser(Model model) {
		
		List<Users>list=this.usersService.findAllUser();
		model.addAttribute("list", list);
		return "findAllUser";
	}
	
	@RequestMapping("/findUser")
	public String findUserById(Integer userid,Model model) {
		
		Users user = this.usersService.findUserById(userid);
		model.addAttribute("user", user);
		return "updateUser";
		
	}
	
	@RequestMapping("/update")
	public String updateUser(Users users) {
		
		this.usersService.updateUser(users);
		return "ok";
	}
	
	@RequestMapping("/delete")
	public String deleteUser(Integer userid) {
		
		this.usersService.deleteUser(userid);
		return "redirect:findAll";
	}
}

编写前台页面

注意 : 1.页面后缀全部都是 .html而不是jsp ,使用的是 ThymeLeaf 可以对 Html页面进行传值操作 2. 下面代码可用于点击用户时将用户id信息传入对应的Controller的方法中

<a th:href="@{/user/findUser(userid=${user.userid})}">   

addUser.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form th:action="@{/user/add}">
		用户姓名: <input type="text" name="username"><br> 
		用户年龄: <input type="text" name="userage"><br>
		<input type="submit" value="添加">
	</form>
</body>
</html>

findAllUser.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户查询界面</title>
</head>
<body>
	<table border="1" style="width: 400px" align="center">
		<tr>
			<th>用户id</th>
			<th>用户姓名</th>
			<th>用户年龄</th>
			<th>操作</th>
		</tr>
		<tr th:each="user:${list}">
			<td th:text="${user.userid}"></td>
			<td th:text="${user.username}"></td>
			<td th:text="${user.userage}"></td>
			<td><a th:href="@{/user/findUser(userid=${user.userid})}">更新</a>
				<a th:href="@{/user/delete(userid=${user.userid})}">删除</a>
			</td>
		</tr>
	</table>
</body>
</html>

ok.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>操作提示页面</title>
</head>
<body>
	<h1>操作成功</h1>
</body>
</html>

updateUser.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户更新页面</title>
</head>
<body>
	<form th:action="@{/user/update}">
		<input type="hidden" name="userid" th:field="${user.userid}">
		用户姓名: <input type="text" name="username" th:field="${user.username}"><br> 
		用户年龄: <input type="text" name="userage" th:field="${user.userage}"><br>
		<input type="submit" value="更新">
	</form>
</body>
</html>