springboot+thymeleaf+springbootJPA实现一个简单的增删改查
1.springboot是什么,给我们带来了什么方便?
通过阅读springboot的书籍发现springboot最便利的是为我们自动配置了很多的东西,几乎可以实现无xml,甚至简单的无sql,为我们带来了很大的遍历,下面我们看看springboot为我们提供了那些配置:
这些所有的包都可以在spring-boot-autoconfigure上都可以看到
2.这里做的是一个学生表
package com.yangchao.spring.boot.blog.domain; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import org.hibernate.validator.constraints.NotEmpty; @Entity public class Student implements Serializable { /** * */ private static final long serialVersionUID = 1L; //标识其是一个主键id @Id @GeneratedValue(strategy = GenerationType.IDENTITY)//表示其增长策略为自增长 private Long id;//学生的唯一标识 @NotEmpty(message = "姓名不能为空") @Column(nullable = false, length = 20,name="name") // 映射为字段,值不能为空,name标识的是数据库的名字 private String name;//学生的姓名 @NotEmpty(message = "性别不能为空")//NotEmpty只能针对字符型才能进行判断空 @Column(nullable = false, length =2,name="sex") // 映射为字段,值不能为空,name标识的是数据库的名字 private String sex; @Column(nullable = false,name="age") // 映射为字段,值不能为空,name标识的是数据库的名字 private Integer age; @Column(name="course_id") private Integer course_id;//学生所选的所有课程 protected Student() {//按照JPA规范定义的一个protected的构造函数,防止被外部使用 } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public void setName(String name) { this.name = name; } public Integer getCourse_id() { return course_id; } public void setCourse_id(Integer course_id) { this.course_id = course_id; } public Student(String name, String sex, Integer age, Integer course_id) { super(); this.name = name; this.sex = sex; this.age = age; this.course_id = course_id; } /** * 重写tostring的原因其实就是数据的传输,所以也必须实现序列化接口serialize接口 * 自从jquery1.9后,json的格式必须满足的是:[{"key":"value"},{"key":"value"}]的格式,除了Boolean型不需要外,其余都是需要的 */ @Override public String toString() { // TODO Auto-generated method stub return "{\"id\":"+"\""+getId()+"\""+","+"\""+name+"\":"+"\""+"getName()"+"\","+"\""+sex+"\":"+"\""+"getSex()"+"\","+"\""+age+"\":"+"\""+getAge()+"\""; } }
3.需要引入的依赖
// buildscript 代码块中脚本优先执行 buildscript { // ext 用于定义动态属性 ext { springBootVersion = '1.5.2.RELEASE' } // 自定义 Thymeleaf 和 Thymeleaf Layout Dialect 的版本 ext['thymeleaf.version'] = '3.0.3.RELEASE' ext['thymeleaf-layout-dialect.version'] = '2.2.0' // 自定义 Hibernate 的版本 ext['hibernate.version'] = '5.2.8.Final' // 使用了 Maven 的中央仓库(你也可以指定其他仓库) repositories { //mavenCentral() maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } } // 依赖关系 dependencies { // classpath 声明说明了在执行其余的脚本时,ClassLoader 可以使用这些依赖项 classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } // 使用插件 apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' // 打包的类型为 jar,并指定了生成的打包的文件名称和版本 jar { baseName = 'blog-comment' version = '1.0.0' } // 指定编译 .java 文件的 JDK 版本 sourceCompatibility = 1.8 // 默认使用了 Maven 的中央仓库。这里改用自定义的镜像库 repositories { //mavenCentral() maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } } // 依赖关系 dependencies { // 该依赖对于编译发行是必须的 compile('org.springframework.boot:spring-boot-starter-web') // 添加 Thymeleaf 的依赖 compile('org.springframework.boot:spring-boot-starter-thymeleaf') // 添加 Spring Data JPA 的依赖 compile('org.springframework.boot:spring-boot-starter-data-jpa') // 添加 MySQL连接驱动 的依赖 compile('mysql:mysql-connector-java:6.0.5') // 添加 Apache Commons Lang 依赖 compile('org.apache.commons:commons-lang3:3.5') // 该依赖对于编译测试是必须的,默认包含编译产品依赖和编译时依 testCompile('org.springframework.boot:spring-boot-starter-test') }
3.JPA
package com.waylau.spring.boot.blog.repository; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import com.waylau.spring.boot.blog.domain.Student; /** * 使用JPA自定义接口进行实现,少些代码 * 这个例子在原有的接口方法上多定义了一些方法,以便应用 * @author lenovo * */ public interface StudentRepository extends JpaRepository<Student, Long> { //根据方法名实现底层自动化生成sql,根据学生性别查询学生信息 List<Student> findBySex(String sex); //根据学生的姓模糊查询学生的详细信息,该方法名等同于where name like ?1; @Query("select s from Student s where name like CONCAT('%',:name,'%')") List<Student> findByNameLike(@Param("name") String name); //根据学生年龄段查询学生的详细信息 List<Student> findByAgeBetween(Integer age1,Integer age2); //如果感觉JPA不能满足需求也可以自定义sql;注意这里占位符?后面是数字1,select后面不能使用*,必须要给表取个别名,否则会报错 @Query("select s from Student s where s.name =?1") List<Student> getStudent(); }
4.定义学生类接口和实现类
package com.waylau.spring.boot.blog.service; import java.util.List; import com.waylau.spring.boot.blog.domain.Student; public interface StudentService { /** * 增加学生 * @param student * @return */ Student saveStudent(Student student); /** * 删除单个学生 * @param id * @return */ void removeStudent(Long id); /** * 更新学生信息 * @param student * @return */ Student updateStudent(Student student); /** * 根据id获取学生信息 * @param id * @return */ Student getStudentById(Long id); /** * 获取学生列表 * @param user * @return */ List<Student> listStudents(); /** * 根据前台的姓名,性别,年龄进行查询学生的基本信息 * @param name * @param sex * @param age * @return */ List<Student> listStudentsByNameAndAgeAndSex(String name,String sex,Integer age1,Integer age2); }
package com.waylau.spring.boot.blog.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.waylau.spring.boot.blog.domain.Student; import com.waylau.spring.boot.blog.repository.StudentRepository; @Service public class StudentServiceImpl implements StudentService{ //注入StudentRepositoryJPA @Autowired StudentRepository studentReposutory; @Override public Student saveStudent(Student student) { // TODO Auto-generated method stub return studentReposutory.save(student); } @Override public void removeStudent(Long id) { // TODO Auto-generated method stub studentReposutory.delete(id); } @Override public Student updateStudent(Student student) { // TODO Auto-generated method stub return studentReposutory.save(student); } @Override public Student getStudentById(Long id) { // TODO Auto-generated method stub return studentReposutory.findOne(id); } @Override public List<Student> listStudents() { // TODO Auto-generated method stub return studentReposutory.findAll(); } @Override public List<Student> listStudentsByNameAndAgeAndSex(String name, String sex,Integer age1,Integer age2) { // TODO Auto-generated method stub if(name != null) { return studentReposutory.findByNameLike(name); }else if(sex != null) { return studentReposutory.findBySex(sex); }else { return studentReposutory.findByAgeBetween(age1,age2); } } }
5.controller层
package com.waylau.spring.boot.blog.controller; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; import com.waylau.spring.boot.blog.domain.Student; import com.waylau.spring.boot.blog.service.StudentService; import net.minidev.json.JSONArray; @RestController//使用rest风格实现controller映射 @RequestMapping("/user") public class StudentController { @Autowired StudentService studentService; /** * 通过Get请求user,直接进入到这里的映射中 * @param model * @return */ @GetMapping public ModelAndView queryAllStudent(Model model) { List<Student> students = studentService.listStudents(); model.addAttribute("allStudent", students); model.addAttribute("title","学生信息表"); return new ModelAndView("index", "userModel", model); } /** * 根据id查询学生的详细信息 */ @GetMapping("{id}")//通过传递的是一个参数id进行的映射 public ModelAndView view(@PathVariable("id") Long id,Model model){ Student student = studentService.getStudentById(id); model.addAttribute("student",student); model.addAttribute("sex",student.getSex()); model.addAttribute("title","查看学生"); return new ModelAndView("view","userModel",model); } /** * 返回学生新增界面 * @param model * @return */ @RequestMapping("add") public ModelAndView addStudent(Model model) { model.addAttribute("title","新增"); return new ModelAndView("add","userModel",model); } // /** // * 新增学生 // * @param student // * @return // */ // @RequestMapping("insert") // public ModelAndView insertStudent(HttpServletRequest req,Model model) { // String name = req.getParameter("name"); // Integer age =Integer.parseInt(req.getParameter("age")); // String sex = req.getParameter("sex"); // String[] course_ids = req.getParameterValues("course_id"); // Integer course_id = Integer.parseInt(course_ids[0]); // Student student = new Student(name,sex,age,course_id); // studentService.saveStudent(student); // return new ModelAndView("redirect:/user");//重新定向到index页面 // } /** * 这里直接定义Student对象,前端使用 * th:value="*{name}",和后端的对象直接进行了映射 * @param student * @param model * @return */ @RequestMapping("insert") public ModelAndView insertStudent(Student student) { studentService.saveStudent(student); return new ModelAndView("redirect:/user");//重新定向到index页面 } /** * 学生信息的删除 * @param id * @param model * @return */ @GetMapping("del/{id}") public ModelAndView deleteStudent(@PathVariable("id") Long id,Model model) { studentService.removeStudent(id); return new ModelAndView("redirect:/user");//重新定向到index页面 } /** * 学生信息的修改 * @param student * @return */ @PostMapping public ModelAndView updateStudent(Student student) { studentService.updateStudent(student); return new ModelAndView("redirect:/user");//重新定向到index页面 } /** * 根据姓名查询学生详细信息 * @param req * @param model * @return * @throws IOException */ @PostMapping("queryStudentByCondition") public void queryStudentByCondition(HttpServletRequest req,HttpServletResponse response) throws IOException { String name = req.getParameter("name"); //防止前台的乱码问题 response.setCharacterEncoding("utf-8"); String sex = null; Integer age1 = null; Integer age2 = null; List<Student> students = studentService.listStudentsByNameAndAgeAndSex(name, sex, age1, age2); PrintWriter wirte; //声明JSONArray对象并输入JSON字符串 String array = JSONArray.toJSONString(students); wirte = response.getWriter(); wirte.print(array); } }
6.jsp学生列表页面index.jsp
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <!-- 定义页面显示的编码格式 --> <meta charset="utf-8"> <script th:src="@{../js/jquery-3.1.1.min.js}"></script> <script> function queryStudentByName(){ $.ajax({ type:'POST', data:{name:'杨超'}, url:"/user/queryStudentByCondition",//请求的action路径 success:function(returnValue){ //请求成功后处理函数。 //处理后端传送过来json格式数据 var msg=jQuery.parseJSON(returnValue); }, error:function () {//请求失败处理函数 alert('请求失败'); } }); } </script> </head> <body> <!-- 获取model属性中的title值,定义标题 --> <h3 th:text="${userModel.title}"></h3> <input type="search" onblur="queryStudentByName()" id="name"/> <div> <a href="add.html" th:href="@{/user/add}">新增</a> </div> <table border="1"> <thead> <tr> <td>id</td> <td>姓名</td> <td>性别</td> <td>年龄</td> <td>课程</td> <td>删除</td> </tr> </thead> <!--对于学生信息做一个判断,没有显示一个默认的 --> <tr th:if="${userModel.allStudent.size()} eq 0"> <td colspan="3">没有学生信息</td> </tr> <!-- 对学生信息进行迭代 --> <tbody id="tbody"> <tr th:each="user : ${userModel.allStudent}"> <!-- 类似于jstl的用法,可以直接从上面的对象中获取值 --> <td th:text="${user.id}"></td> <td><a th:href="@{'/user/'+${user.id}}" th:text="${user.name}"></a></td> <!-- 动态生成一个查看用户信息的链接 --> <td th:text="${user.sex}"></td> <td th:text="${user.age}"></td> <td th:text="${user.course_id}"></td> <td ><a th:href="@{'/user/del/'+${user.id}}">删除</a></td> </tr> </tbody> </table> </body> </html>
新增页面add.jsp
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h3 th:text="@{userModel.title}"></h3> <form action="/user/insert" method="post"> <input type="hidden" name="id" th:value="*{id}"/> 姓名:<input type="text" placeholder="姓名" name="name" th:value="*{name}" /></br> 年龄:<input type="text" placeholder="年龄" name="age" th:value="*{age}" /></br> 性别:<select name="sex" th:value="*{sex}"> <option value="男">男</option> <option value="女">女</option> </select> 选课:<input type="checkbox" name="course_id" value="1"/>语文 <input type="checkbox" name="course_id" value="2"/>数学 <input type="checkbox" name="course_id" value="3"/>英语</br> <input type="submit" value="提交"/> <input style="margin-left:30px" type="button" value="取消"/> </form> </body> </html>
显示和修改页面:view.jsp
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>学生详细信息</title> <script th:src="@{../js/jquery-3.1.1.min.js}"></script> </head> <!-- 为了在js中使用thymeleaf --> <script th:inline="javascript"> //将下拉框和复选框进行选中 function onload(){ //在js中引用thymeleaf的语法 var sex = [[${userModel.student.sex}]]; document.getElementById("sex").value =sex; var course = [[${userModel.student.course_id}]]; $("input:checkbox[value='"+course+"']").attr("checked","checked"); } </script> <body onload="onload()"> <form action="/user" method="post" th:object="${userModel.student}"> <input type="hidden" name="id" th:value="*{id}" /> 姓名:<input type="text" placeholder="姓名" name="name" th:value="*{name}" /></br> 年龄:<input type="text" placeholder="年龄" name="age" th:value="*{age}" /></br> 性别:<select name="sex" th:value="*{sex}" id="sex"> <option value="男">男</option> <option value="女">女</option> </select> 选课:<input type="checkbox" name="course_id" value="1" id="1"/>语文 <input type="checkbox" name="course_id" value="2" id="2"/>数学 <input type="checkbox" name="course_id" value="3" id="3"/>英语</br> <input type="submit" value="修改"/> <input style="margin-left:30px" type="button" value="取消"/> </form> </body> </html>
7.application.properties配置
server.port=8080 debug=false # THYMELEAF spring.thymeleaf.encoding=UTF-8 # 热部署静态文件 spring.thymeleaf.cache=false # 使用HTML5标准 spring.thymeleaf.mode=HTML5 # DataSource spring.datasource.url=jdbc:mysql://localhost/blog?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # JPA,表示是否在控制台输出sql spring.jpa.show-sql=true #使用hibernate创建表格,是否将已存在的表格进行删除,这个配置只适用于生产测试环节 spring.jpa.hibernate.ddl-auto=create-drop
今天写的有点冲忙,后面再做详细解释.我将源码附在后面,各位可自行下载
https://pan.baidu.com/s/1smjNqUT
减压密码:957p