赞
踩
目录
产生背景:
本人要参加某个全国计算机比赛,要求在4小时内局域网环境内编写B/S程序。4个小时的比赛时间非常紧张,于是需要准备能快速并且最少配置的搭建开发框架。因为没有互联网,就无法百度,无法查阅资料,一旦配置出错,后果是灾难性的。赛前在各种网站上一直没有找到最简单的增删改查,有的都是浅尝辄止的Hello World。于是,赛后我觉得一定要自己做个最简洁最高效的CUAD。并且要把关键代码直接贴到博客里,而不仅仅是的放到压缩包里。
内容说明:
本文用最简的POM文件、最简的层次结构(Controller\Service\DAO\Model)、最简的DAO类、最简的实体类,采用Spring-DATA-JPA 、Thymeleaf技术来最终实现表的增删改查。若你发现你不会使用Spring Data JPA,不会使用Thymeleaf,不要紧很简单,看完案例,你会发现这些技术都很基础和简单。用上它们才是简洁制胜的法宝。
声明:
本例仅适用于【无互联网环境 / 仅有 Maven本地库可用】的艰苦情况下使用Spring Boot快速开发方案(需要记忆的配置最少)。互联网环境不必如此麻烦。
本例也不适合用于实际项目,仅用于快速开发,在有限时间内做出成品。如需用于实际项目,最好将Service定义为接口,然后再实现。方便以后业务变更时,可以使用不同的 ServiceImpl 实现。
错误说明:com.zxb.controller 包名起的稍微有些问题,应为com.zxb,手快打错了,图片无法修改,故此说明。
项目结构:
IDE:IntelliJ IDEA 2017.3 专业版(收费版)。破解方法自寻。
Maven 3.6.1
此步非本文重点,不作截图,仅文字描述。我们这里使用从maven处新建项目,所以保证您和maven服务器之间有网络连接。无论您连接的是互联网maven官网,或是局域网内的maven服务器。请确保maven服务器上有本文所需要的全部 jar 包。
准备工作:将默认的国外Maven仓库更改为国内的阿里云Maven仓库,加快jar包的导入和下载速度。
在 C:\Users\Administrator\.m2 (安装IDEA后,在个人用户目录下创建)目录下,新建文件:settings.xml ,内容为:
- <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
- https://maven.apache.org/xsd/settings-1.0.0.xsd">
-
- <mirrors>
- <mirror>
- <id>alimaven</id>
- <name>aliyun maven</name>
- <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
- <mirrorOf>central</mirrorOf>
- </mirror>
- </mirrors>
- </settings>
下面是最简的POM.xml。
- <?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>
-
- <groupId>com.zxb</groupId>
- <artifactId>testBoot</artifactId>
- <version>1.0-SNAPSHOT</version>
- <!-- 指定Spring Boot的版本 2.0.4.RELEASE -->
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.0.4.RELEASE</version>
- </parent>
-
- <dependencies>
- <!-- 导入Spirng Boot web 所需的jar包 -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-jpa</artifactId>
- </dependency>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-thymeleaf</artifactId>
- </dependency>
- </dependencies>
-
- <packaging>jar</packaging>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-resources-plugin</artifactId>
- <version>3.1.0</version>
- </plugin>
- </plugins>
- </build>
- </project>
仅需配置 Spring boot、spring-boot-starter-web(可以连接为Spring Booter核心)、spring-boot-starter-data-jpa(ORM持久层接口)、spring-boot-starter-thymeleaf(Spring Boot推荐的替代JSP的模板引擎)、mysql-connector-jara(连接mysql)。
这五个jar包就足够搭建个完整的可以对MySQL进行增删改查,页面遍历复杂列表数据的网站系统了。
如果你觉得没学过 Thymeleaf模板引擎,可以先看下去,你会发现它其实很简单,和<c:if>之流类似。
POM.xml文件编写好后,然后在IDEA的maven窗口右键 Reimport 一下,IDEA会自动导入POM.xml中所需要的jar包。
MyMain.java
- package com.zxb.controller;
-
-
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
- import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
-
- /**
- * @SpringBootApplication:标注一个主程序类,用来标明这是一个Spring Boot应用
- */
- @EnableAutoConfiguration
- @SpringBootApplication
- @EnableJpaRepositories
- public class MyMain {
- // Spring应用启动起来
- public static void main(String[] args) {
-
- SpringApplication.run(MyMain.class,args);
- }
- }
启动类写完,就可 Run 一次了。可以在浏览器中打开 http://localhost:8080,可以看到有文字显示。
至此,Spring Boot版本的Hello World就完成了,可以说这些步骤毫无使用价值。下面看如何实现MySQL表的增删改查,包括model/Entity/POJO层、Service层、DAO层、Controller层设计。
注意:在新版的Spring Boot中,需要先在 application.properties 配置 数据库连接 才能运行起来。可将如下内容复制到 application.properties中:
- #使用Spring Boot默认的thymeleat模板引擎,可不用显示配置视图解析器,仅需将html等文件
- #放在指定的默认目录: resources/template 下即可。切记resources 复数形式的s不可丢,否则报错。
-
- #mysql
- #注意设置MYSQL的sever/database/table必须全设置为utf-8
- #注意设置IDEA的所有encoding编码均为utf-8
- #注意本配置文件中的url必须加上?后的参数,否则会出现汉字乱码!
- #注意加上serverTimezone保你平安,否则启动SpringBoot出现Timezone错误
- #版本越高spring boot屁事儿越多
- spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
- spring.datasource.username=root
- spring.datasource.password=123456
- spring.datasource.driverclass=com.mysql.jdbc.Driver
- spring.datasource.driver-class-name=com.mysql.jdbc.Driver
这个项目里,我们全使用注解,不需一个实体类映射文件,也不需要任何Mybatis的xml文件。简洁高效,这才是理想的开发。举个例子。
BookEntity.java
- package com.zxb.controller.model;
-
- import java.io.Serializable;
- import javax.persistence.*;
-
- @Entity
- @Table(name="bookstore")
- public class BookEntity implements Serializable{
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- protected Long id;
-
- public String getStorename() {
- return storename;
- }
-
- public void setStorename(String storename) {
- this.storename = storename;
- }
-
- @Column(name = "storename")
- protected String storename;
-
- public String getLocation() {
- return location;
- }
-
- public void setLocation(String location) {
- this.location = location;
- }
-
- @Column(name = "location")
- protected String location;
-
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
-
-
- }
看看这个DAO层(与数据库交互的层)有多简单,这全都是Spring Data JPA框架的功劳。
BookDAO.java
- package com.zxb.controller.dao;
-
- import com.zxb.controller.model.BookEntity;
- import org.springframework.data.jpa.repository.JpaRepository;
- import org.springframework.data.jpa.repository.Query;
- import org.springframework.data.repository.query.Param;
- import org.springframework.stereotype.Repository;
- import java.util.List;
-
- @Repository
- public interface BookDAO extends JpaRepository<BookEntity, Integer>{
-
- public BookEntity findById(Long id);
-
- public BookEntity save(BookEntity user);
-
- @Query(value = "SELECT u FROM BookEntity u WHERE storename=:storename")
- public BookEntity findName(@Param("storename") String storename);
-
- @Query(value="select u FROM BookEntity u ")
- public List<BookEntity> findAll();
-
- }
当然,这里仅仅列举了最简单的几个函数,但从中可以窥见 Spring Data JPA技术为我们做了很多的工作。我们既然选用Spring Boot,却为何放这么好的工具不用呢,却手动去造轮子,重复编写 MyBaits 查询?
这里是使用了注解形式进行查询,注解中的查询语句既可以是Hibernate的HQL语句,也可以是 原声的 SQL语句。若想使用原生态的SQL语句,则可以使用这个注解:
@Query(value="select * from Book" ,nativeQuery = true)
native=true的意思就是使用原生的SQL查询。
我们仔细看看这个写法。注意:这个 BookDAO 不是个类,而是个 Interface,继承了 JpaRepository 这个Spring Data JPA给我们设计好的数据库持久接口,我们可以打开这个 JpaRepository,看看它给我们已经做好了哪些工作。
- package org.springframework.data.jpa.repository;
-
- import java.util.List;
- import org.springframework.data.domain.Example;
- import org.springframework.data.domain.Sort;
- import org.springframework.data.repository.NoRepositoryBean;
- import org.springframework.data.repository.PagingAndSortingRepository;
- import org.springframework.data.repository.query.QueryByExampleExecutor;
-
- @NoRepositoryBean
- public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
- List<T> findAll();
-
- List<T> findAll(Sort var1);
-
- List<T> findAllById(Iterable<ID> var1);
-
- <S extends T> List<S> saveAll(Iterable<S> var1);
-
- void flush();
-
- <S extends T> S saveAndFlush(S var1);
-
- void deleteInBatch(Iterable<T> var1);
-
- void deleteAllInBatch();
-
- T getOne(ID var1);
-
- <S extends T> List<S> findAll(Example<S> var1);
-
- <S extends T> List<S> findAll(Example<S> var1, Sort var2);
- }
其实,这里面还有很多智能化的东西,我没有深入去研究。大家可以自己去搜索,Spring Data JPA的用法。下面我们看看这个DAO接口如何使用,我贴出Service层。
关于Spring data jpa更详细的文章见此链接。
最详细的Spring-data-jpa入门(一)_此成非彼诚的博客-CSDN博客_springdatajpa
BookService.java
- package com.zxb.controller.service;
-
- import com.zxb.controller.dao.BookDAO;
- import com.zxb.controller.model.BookEntity;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
-
- import java.util.List;
-
- @Service
- public class BookService {
- @Autowired
- private BookDAO bookDAO;
-
- public void save(BookEntity bookEntity){
- bookDAO.save(bookEntity);
- }
-
- public List list(){
- return bookDAO.findAll();
- }
- }
如上图所示,我们的 BookDAO 接口是可以直接使用的,无需实现该接口的继承类。并且还可以直接使用 BookDAO 的父亲接口 ,也就是 Spring Data JPA给我们设计好的 JpaRepository 里面的通用方法,是不是超简单。
Controller层已经很简单,还是普通的用法。
TestContoller.java
- package com.zxb.controller.control;
-
- import com.zxb.controller.model.BookEntity;
- import com.zxb.controller.service.BookService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.ResponseBody;
- import org.springframework.web.servlet.ModelAndView;
-
- import java.awt.print.Book;
- import java.util.List;
-
- @Controller
- @EnableAutoConfiguration
- public class TestController {
-
- @Autowired
- private BookService bookService;
-
- //系统首页
- @RequestMapping("/")
- @ResponseBody
- public String index(){
- return "Hello Spring Boot.访问http://localhost:8080/book/add进行新增测试;访问http://localhost:8080/book/list查看列表";
- }
-
- //跳转至录入页面
- @RequestMapping("/book/add")
- public ModelAndView add(){
- System.out.print("add..............");
- ModelAndView mv = new ModelAndView();
- mv.setViewName("add");
- return mv;
- }
-
- //跳转至列表页面
- @RequestMapping("/book/list")
- public ModelAndView list(){
- List<BookEntity> bookList = bookService.list();
- // for (int i = 0; i < bookList.size(); i++) {
- // System.out.print("---------------------"+bookList.get(i).getId());
- // }
- ModelAndView mv = new ModelAndView();
- mv.setViewName("list");
- mv.addObject("bookList",bookList);
-
- return mv;
- }
-
- //保存表单
- @RequestMapping("/book/save")
- public String save(@RequestParam(name="bookstore")
- String storename, @RequestParam(name="location") String location){
- BookEntity bookEntity = new BookEntity();
- System.out.print(storename);
- bookEntity.setStorename(storename);
- bookEntity.setLocation(location);
- bookService.save(bookEntity);
- System.out.print(bookEntity.getStorename());
- return "redirect:/book/list";
- }
-
-
- }
我很反感这样的层次结构:
sevice/serviceImple、DAO/DAOImpl、BookEntity/BookEntity.hbm.xml/Mapper.xml。
我觉得软件应以生产效率为目标,而坚持非死板的教条主义。我也做过有些规模的软件项目,这样的结构并没有想象中的那样灵活,更多时候在出现需求变更时,我们直接全都是新建类、新建方法,全都是新建,并没有体现出接口和接口实现的作用。我不否认自己未严格按照最优设计去做。但还是要务实些,这些接口和接口实现不会在实践中出现。
我认为小项目结构更适合这个:
Contoller、单层Service、单层DAO、单层Model/Entity/POJO。
一切为生产为实际服务。务实,一定要务实。项目大型程度决定设计复杂程度。效率第一。
附上其它文件,使得你可以不用下载zip就能对整个结构有个清晰的了解:
最简配置文件 application.properties:
- #使用Spring Boot默认的thymeleat模板引擎,可不用显示配置视图解析器,仅需将html等文件
- #放在指定的默认目录: resources/template 下即可。切记resources 复数形式的s不可丢,否则报错。
-
- #mysql
- #注意设置MYSQL的sever/database/table必须全设置为utf-8
- #注意设置IDEA的所有encoding编码均为utf-8
- #注意本配置文件中的url必须加上?后的参数,否则会出现汉字乱码!
- #注意加上serverTimezone保你平安,否则启动SpringBoot出现Timezone错误
- #版本越高spring boot屁事儿越多
- spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
- spring.datasource.username=root
- spring.datasource.password=123456
- spring.datasource.driverclass=com.mysql.jdbc.Driver
- spring.datasource.driver-class-name=com.mysql.jdbc.Driver
说明:mysql 的 driver 根据mysql版本的不同而有所不同,若出现错误可以尝试:
com.mysql.cj.jdbc.Driver
这其中,连视图解析器都不用配置。只要你按Spring Boot的默认约定,把HTML都放在 resources/template 目录下。注意这个路径一个字母一个s都不能少。如果你写成 resource/template那就会报错,就需要在配置文件中配置视图解析器!
空无一物的 web.xml,这个仍是默认内容:
- <!DOCTYPE web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd" >
-
- <web-app>
- <display-name>Archetype Created Web Application</display-name>
- </web-app>
增加书籍页面 add.html:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- 新增页面
- <form action="/book/save" method="post">
-
- 书店名称:<input type="text" value="" name="bookstore"/>
- 书店位置:<input type="text" value="" name="location"/>
- <input type="submit" value="提交"/>
- </form>
- </body>
- </html>
列表页面 list.html:
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
- <html xmlns:th="http://www.thymeleaf.org">
- <head >
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>列表页面
- <p th:text="${name}"></p>
-
- <ul th:each="item:${bookList}">
- <li>id:<span th:text="${{item.id}}" /></li>
- <li>书店:<span th:text="${item.storename}"/></li>
- <li>位置:<span th:text="${item.location}"/></li>
- </ul>
-
-
- </body>
- </html>
注意:
1. 列表页面,简单的使用了 thymeleaf 做遍历数据库。
2. 列表页面,使用 thymeleaf 需要在 <html> 根标签处加上 thymeleaf 的命名空间属性。
<html xmlns:th="http://www.thymeleaf.org">
不见此属性,thymeleaf 的标签是不会被识别和解析的。切记。
最后的最后:打包发布。
双击IDEA的Maven窗口中的 package,将会在项目的target目录下生成 jar 文件。此 .jar 文件即可复制到服务器或其它地方运行,运行方法: java -jar myproject.jar。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。