SpringBoot开发常用技术整合

一.接口返回Json

1.使用@RestController代替@Controller和@ResponseBody

2.Jackson的基本演绎法

  • @JsonIgnore返回时不携带的字段

  • @JsonFormat(pattern="yyyy-MM-dd hh:mm:ss a",locale="zh",timezone="GMT+8")返回时按照指定格式转换,pattern样式,locale表示在中国,timezone表示东八区

  • @JsonInclude(Include.NON_NULL)表示该字段为空时将不返回给前端

  • 实例代码

    //User.java
    package com.example.demo2.domain;
    import com.fasterxml.jackson.annotation.JsonFormat;
    import com.fasterxml.jackson.annotation.JsonIgnore;
    import com.fasterxml.jackson.annotation.JsonInclude;
    import java.util.Date;
    public class User{
        private String name;
        @JsonIgnore
        private String password;
        private Integer age;
        @JsonFormat(pattern="yyyy-MM-dd hh:mm:ss a",locale="zh",timezone="GMT+8")
        private Date birthday;
        @JsonInclude(JsonInclude.Include.NON_NULL)
        private String desc;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public String getDesc() {
            return desc;
        }
    
        public void setDesc(String desc) {
            this.desc = desc;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", password='" + password + '\'' +
                    ", age=" + age +
                    ", birthday=" + birthday +
                    ", desc='" + desc + '\'' +
                    '}';
        }
    }
    
    //testController.java
    package com.example.demo2.controller;
    import com.example.demo2.domain.User;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import java.util.Date;
    
    @RestController
    public class testController {
    
        @RequestMapping("getUser")
        public User getUser(){
            User user = new User();
            user.setName("Jack");
            user.setAge(20);
            user.setBirthday(new Date());
            user.setPassword("123");
            //user.setDesc("Jack is smart");
            return user;
        }
    }
    
    //页面输出结果{"name":"Jack","age":20,"birthday":"2018-09-30 10:59:26 下午"}
    

二.SpringBoot热部署

1.Springboot使用devtools进行热部署

  • devtools可以实现页面热部署(即页面修改后会立即生效,这个可以直接在application.properties文件中配置spring.thymeleaf.cache=false来实现),实现对类文件(类文件修改后不会立即生效)和对属性文件的热部署。即devtools会监听classpath下的文件变动,并且会立即重启应用(发生在保存时),注意:因为其采用的虚拟机机制,该项重启是很快的。

  • 配置了后在修改java文件后也就支持了热启动,不过这种方式是属于项目重启(速度比较快的项目重启),会清空session中的值,也就是如果有用户登陆的话,项目重启后需要重新登陆。

    默认情况下,/META-INF/maven,/META-INF/resources,/resources,/static,/templates,/public这些文件夹下的文件修改不会使应用重启,但是会重新加载(devtools内嵌了一个LiveReload server,当资源发生改变时,浏览器刷新)。

  • devtools的原理

    • 类加载时使用了两个ClassLoader,一个Classloader加载那些不会改变的类(第三方Jar包),另一个ClassLoader加载会更改的类,称为restart ClassLoader,这样在有代码更改的时候,原来的restart ClassLoader 被丢弃,重新创建一个restart ClassLoader,由于需要加载的类相比较少,所以实现了较快的重启时间。
    • base classloader(Base类加载器):加载不改变的Class,例如:第三方提供的jar包
    • restart classloader(Restart类加载器):加载正在开发的Class
    • 为什么重启很快,因为重启的时候只是加载了在开发的Class,没有重新加载第三方的jar包。
  • 引入jar包

    
    <dependency>
    	<groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
        
        <optional>trueoptional>
    dependency>
    
    
    compile('org.springframework.boot:spring-boot-devtools')
    
  • application.properties

    #关闭缓存,即时刷新
    spring.thymeleaf.cache=false
    #热部署生效
    spring.devtools.restart.enabled=true
    #设置重启的目录,添加哪个目录的文件需要restart
    spring.devtools.restart.additional-paths=src/main/java
    #为mybatis设置,生产环境可删除
    #restart.include.mapper=/mapper-[\\w-\\.]+jar
    #restart.include.pagehelper=/pagehelper-[\\w-\\.]+jar
    #排除哪个目录的文件不需要restart
    #spring.devtools.restart.exclude=static/**,public/**
    #classpath目录下的WEB-INF文件夹内容修改不重启
    #spring.devtools.restart.exclude=WEB-INF/**
    
  • 当我们修改了Java类后,IDEA默认是不自动编译的,而spring-boot-devtools又是监测classpath下的文件发生变化才会重启应用,所以需要设置IDEA的自动编译

    • Edit Configurations -> on frame deactivation选中Update classes and resources
    • Preferences -> Build,Execution.Deployment -> Compiler选中Build project automatically
  • 测试

    • 修改类–>保存:应用会重启
    • 修改配置文件–>保存:应用会重启
    • 修改页面–>保存:应用不会重启,但会重新加载,页面会刷新(原理是将spring.thymeleaf.cache设为false,参考:Spring Boot配置模板引擎)

三.SpringBoot资源属性配置

1.SpringBoot资源属性配置—资源文件中的属性配置与映射到实体类

  • 想要读取资源文件properties中的内容需要添加如下configuration的依赖

    <dependency>
    	<groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-configuration-processorartifactId>
        <optional>trueoptional>
    dependency>
    
  • 编写资源文件(rousource.properties)

    com.test.opensource.name=Jack
    com.test.opensource.age=20
    com.test.opensource.language=English
    
  • 编写映射的类(Resource.java)

    package com.example.demo2.domain;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    
    @Configuration
    @ConfigurationProperties(prefix = "com.test.opensource")//设置加载属性的前缀
    @PropertySource(value = "classpath:resource.properties")//设置资源文件的地址
    public class Resource {
        private String name;
        private String age;
        private String language;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getAge() {
            return age;
        }
        public void setAge(String age) {
            this.age = age;
        }
        public String getLanguage() {
            return language;
        }
        public void setLanguage(String language) {
            this.language = language;
        }
        @Override
        public String toString() {
            return "Resource{" +
                    "name='" + name + '\'' +
                    ", age='" + age + '\'' +
                    ", language='" + language + '\'' +
                    '}';
        }
    }
    
  • 测试

    @Autowired
    private Resource resource;
    @RequestMapping("getResource")
    public void getResource(){
        System.out.println(resource);
    }
    //输出结果 Resource{name='Jack', age='20', language='English'}
    

2.SpringBoot资源文件配置server以及Tomcat

  • 资源文件配置server相关属性(application.properties)

    #Server服务端相关配置
    #配置api端口号
    server.port=8000
    #配置context-path,一般来说这个配置在正式发布的时候不配置
    server.servlet.context-path=/Test
    #session最大超时时间(分钟),默认为30分钟
    server.session-timeout=60
    #该服务绑定IP地址,启动服务器时如本机不是该IP地址则抛出异常启动失败
    #只有特殊需求的情况下才配置,具体根据各自的业务来设置
    #server.address=192.168.1.100
    
  • Server - tomcat相关常用配置(application.properties)

    #tomcat最大线程数,默认为200
    server.tomcat.max-threads=250
    #tomcat的URI编码
    server.tomcat.uri-encoding=UTF-8
    #存放Tomcat的日志、Dump等文件的临时文件夹,默认为系统的tmp文件夹
    server.tomcat.basedir=H:/springboot-tomcat-tmp
    #打开Tomcat的Access日志,并可以设置日志格式的方法
    server.tomcat.access-log-enabled=true
    server.tomcat.access-log-pattern=
    #accesslog目录,默认在basedir/logs
    server.tomcat.accesslog.directory=
    #日志文件目录
    logging.path=H:/springboot-tomcat-tmp
    #日志文件名称,默认spring.log
    logging.file=myapp.log
    
  • 学习时自己产生的问题:springboot既然可以自己部署,为什么还要用tomcat?

    • spring-boot默认提供内嵌的tomcat,所以打包直接生成jar包,用java -jar命令就可以启动。但是,有时候我们更希望一个tomcat来管理多个项目,这种情况下就需要项目是war格式的包而不是jar格式的包

四.SpringBoot整合模板引擎

  • jsp是在服务端渲染,模板引擎是在客户端渲染,效率更高
  • Spring目前主推thymeleaf,后缀是html

1.SpringBoot整合freemarker

  • 引入freemarker模板依赖

    <dependency>
    	<groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-freemarkerartifactId>
    dependency>
    
  • freemarker静态资源配置(application.properties)

    #设定ftl文件路径,所有页面文件放到templates中
    spring.framemarker.template-loader-path=classpath:/templates
    
    #关闭缓存,即时刷新,上线生产环境需要改为true
    spring.framemarker.cache=false
    spring.framemarker.charset=UTF-8
    spring.framemarker.check-template-location=true
    spring.framemarker.content-type=text/html
    spring.framemarker.expose-request-attributes=true
    spring.framemarker.expose-session-attributes=true
    spring.framemarker.request-context-attribute=request
    #文件后缀.ftl
    spring.framemarker.suffix=.ftl
    
  • 测试部分

    • 创建freemarker.index.ftl页面和freemarker.content.content.ftl页面

      
      
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Titletitle>
      head>
      <body>
      index页面
      body>
      html>
      
      
      
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Titletitle>
      head>
      <body>
      Content页面-ss
      ${resource.name}
      ${resource.age}
      body>
      html>
      
    • 创建controller内容

      package com.example.demo2.controller;
      import com.example.demo2.domain.Resource;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Controller;
      import org.springframework.ui.ModelMap;
      import org.springframework.web.bind.annotation.RequestMapping;
      @Controller
      public class testFreemarker {
          @Autowired
          private Resource resource;
          @RequestMapping("index")
          public String toIndex(){
              System.out.println("进来index");
              return "freemarker/index";
          }
          @RequestMapping("toContent")
          public String toContent(ModelMap map){//ModelMap相当于SpringMVC中的ModelAndView
              map.addAttribute("resource",resource);
              return "freemarker/content/content";
          }
      }
      

2.SpringBoot整合thymeleaf

  • 引入thymeleaf模板依赖

    <dependency>
    	<groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-thymeleafartifactId>
    dependency>
    
  • thymeleaf静态资源配置(application.properties)

    spring.thymeleaf.prefix=classpath:/templates/
    spring.thymeleaf.suffix=.html
    spring.thymeleaf.mode=HTML5
    spring.thymeleaf.encoding=UTF-8
    spring.thymeleaf.content-type=text/html
    #关闭缓存,即时刷新,上线生产环境需要改为true
    spring.thymeleaf.cache=false
    
  • 测试部分

    • 创建thymeleaf.index.html页面和thymeleaf.content.content.html页面

      
      
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Titletitle>
      head>
      <body>
      thymeleaf:index页面
      body>
      html>
      
      
      
      <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
      <head>
          <meta charset="UTF-8">
          <title>Titletitle>
      head>
      <body>
      thymeleaf:Content页面-ss
      <h1 th:text="${name}">hello jackh1>
      body>
      html>
      
      • 其中content.html中使用

        thymeleaf的标签,当页面渲染时没有返回name属性时输出hello jack,有name属性值时输出对应name值

    • controller内容

      package com.example.demo2.controller;
      import com.example.demo2.domain.Resource;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Controller;
      import org.springframework.ui.ModelMap;
      import org.springframework.web.bind.annotation.RequestMapping;
      @Controller
      public class testThymeleaf {
          @RequestMapping("thymeleaf/index")
          public String toIndex(){
              return "thymeleaf/index";
          }
      
          @RequestMapping("thymeleaf/toContent")
          public String toContent(ModelMap map){
              map.addAttribute("name","jack");
              return "thymeleaf/content/content";
          }
      }
      

3.thymeleaf常用标签的使用方法

  • 基本使用方式

    • th:id="${user.name}"表示该dom节点的id属性值为name的值
    • th:name="${user.name}"表示该dom节点的name属性值为name的值
    • th:value="${user.name}"表示该dom节点的value属性值为name的值
    • th:value="${#dates.format(user.birthday,'dd/MM/yyyy')}"可以使用这种方式对birthday的值进行格式化并赋给dom节点的value属性值
    <div>
        <input th:id="${user.name}" th:name="${user.name}" th:value="${user.name}"/>
        <input th:value="${#dates.format(user.birthday,'dd/MM/yyyy')}"/>
    div>
    
  • 对象引用方式

    <div th:object="${user}">
        用户姓名:<input th:id="*{name}" th:name="*{name}" th:value="*{name}"/>
        <br/>
        用户年龄:<input th:value="*{age}"/>
        <br/>
        用户生日:<input th:value="*{#dates.format(birthday,'yyyy-MM-dd hh:mm:ss')}"/>
        <br/>
    div>
    
    • th:object="${user}"表示该节点的子节点可以利用该对象的引用
    • th:value="*{name}"利用*{}的方式引用对象中的属性
    • 注意:使用了对象引用则子节点使用时直接使用属性名即可,不要再加上对象名,否则报错
  • 时间类型转换

    • 使用th:value="${#dates.format(birthday,'dd/MM/yyyy')}"方式对birthday的值进行格式化并赋给dom节点的value属性值
  • text与utext

    • 使用th:text=${user.desc}原封不动的user.desc中的内容解析输出

    • 使用th:utext=${user.desc}会将html代码进行转译并输出

    • 实例

      
      <span th:text=${user.desc}>abcspan>
      <span th:utext=${user.desc}>abcspan>
      
      
      
  • URL

  • 引入静态资源文件js/css

    • application.properties中设定静态文件路径js和css等(其中静态文件在src/main/resource/static下)

      spring.mvc.static-path-pattern=/static/**
      
    • 页面引入静态资源

      <script th:src="@{/static/js/test.js}">script>
      
  • 表单

    <form th:action="@{/th/postform}" th:object="${user}" method="post" th:method="post">
        <input type="text" th:field="*{name}"/>
        <input type="submit"/>
    form>
    
    • 使用th:action="@{地址}"的形式设置目标地址
    • 设置请求方式使用mathod="post"th:method="post"都可以
    • 使用th:field="*{name}"表示会自动把其解释成th:id="*{name}" th:name="*{name}" th:value="*{name}"【推荐写法,但需要跟th:object="${user}"配合使用】
  • 条件判断 th:if

    • th:if="${user.age} == 18"表示等于

    • th:if="${user.age} gt 18"表示大于(t表示than)

    • th:if="${user.age} lt 18"表示小于

    • th:if="${user.age} ge 18"表示大于等于(e表示equal)

    • th:if="${user.age} le 18"表示小于等于

    • 注意条件判断可以使用三元表达式进行正确和错误的不同处理,详见下方循环中的实例

    • 通过判断决定当前内容是否显示

      • 实例1

        <div th:if="${user.age} == 18">等于div>
        <div th:if="${user.age} gt 18">大于div>
        <div th:if="${user.age} lt 18">小于div>
        <div th:if="${user.age} ge 18">大于等于div>
        <div th:if="${user.age} le 18">小于等于div>
        
        
      • 实例2:在select中使用

        <select>
            <option>选择框option>
            <option th:selected="${user.name eq 'jack'}">jackoption>
            <option th:selected="${user.name eq 'lucy'}">lucyoption>
            <option th:selected="${user.name eq 'lee'}">leeoption>
        select>
        
        
  • th:unlessth:if使用相反(不常用,了解即可)

  • 循环th:each

    <table>
        <tr>
        	<th>姓名th>
            <th>年龄th>
            <th>年龄备注th>
            <th>生日th>
        tr>
        <tr th:each="person:${userlist}">
            <td th:text="${person.name}">td>
            <td th:text="${person.age}">td>
            <td th:text="${person.age gt 18} ? 你老了:你很年轻">18岁td>
            <td th:text="${#dates.format(user.birthday,'yyyy-MM-dd hh:mm:ss')}">td>
        tr>
    table>
    
    
    • 使用th:each="元素:${集合}"循环将集合中的元素取出
  • th:switchth:case

    <div th:switch="${user.name}">
        <p th:case="'jack'">超级管理员p>
        <p th:case="#{roles.manager}">普通管理员p>
        <p th:case="*">其他用户p>
    div>
    
    • 使用th:switch="${user.name}"进行选项内容选取,利用th:case="'具体'"内容匹配则输出对应内容
  • 综合代码

    • index.html

      
      <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
      <head>
          <meta charset="UTF-8">
          <title>Titletitle>
          <script th:src="@{/static/js/test.js}">script>
      head>
      <body>
      thymeleaf:index页面
      <div>
          <input th:id="${user.name}" th:name="${user.name}" th:value="${user.name}"/>
          <input th:value="${#dates.format(user.birthday,'dd/MM/yyyy')}"/>
      div>
          
      <div th:object="${user}">
          用户姓名:<input th:id="*{name}" th:name="*{name}" th:value="*{name}"/>
          <br/>
          用户年龄:<input th:value="*{age}"/>
          <br/>
          用户生日:<input th:value="*{#dates.format(birthday,'yyyy-MM-dd hh:mm:ss')}"/>
          <br/>
      div>
          
      <div th:text="${user.desc}">这是一段描述div>
      <div th:utext="${user.desc}">这也是一段描述div>
      <a th:href="@{http://www.baidu.com}">百度a>
          
      <form th:action="@{/th/postform}" th:object="${user}" th:method="post">
          <input type="text" th:field="*{name}"/>
          <input type="submit">
      form>
          
      <div th:if="${user.age} == 18">等于div>
      <div th:if="${user.age} gt 18">大于div>
      <div th:if="${user.age} lt 18">小于div>
      <div th:if="${user.age} ge 18">大于等于div>
      <div th:if="${user.age} le 18">小于等于div>
          
      <select>
          <option>选择框option>
          <option th:selected="${user.name eq 'jack'}">jackoption>
          <option th:selected="${user.name eq 'lucy'}">lucyoption>
          <option th:selected="${user.name eq 'lee'}">leeoption>
      select>
      
      <table>
          <tr>
              <th>姓名th>
              <th>年龄th>
              <th>年龄备注th>
              <th>生日th>
          tr>
          <tr th:each="person:${userlist}">
              <td th:text="${person.name}">td>
              <td th:text="${person.age}">td>
              <td th:text="${person.age gt 18} ? 你老了:你很年轻">18岁td>
              <td th:text="${#dates.format(user.birthday,'yyyy-MM-dd hh:mm:ss')}">td>
          tr>
      table>
      
      <div th:switch="${user.name}">
          <p th:case="'jack'">超级管理员p>
          <p th:case="#{roles.manager}">普通管理员p>
          <p th:case="*">其他用户p>
      div>
      
      body>
      html>
      
    • testThymeleaf.java

      package com.example.demo2.controller;
      import com.example.demo2.domain.Resource;
      import com.example.demo2.domain.User;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Controller;
      import org.springframework.ui.ModelMap;
      import org.springframework.web.bind.annotation.PostMapping;
      import org.springframework.web.bind.annotation.RequestMapping;
      import java.util.ArrayList;
      import java.util.Date;
      import java.util.List;
      
      @Controller
      public class testThymeleaf {
      
          @RequestMapping("thymeleaf/index")
          public String toIndex(ModelMap map){
              List<User> users = new ArrayList<User>();
              User user = new User();
              user.setName("jacks");
              user.setAge(20);
              user.setPassword("1234");
              user.setBirthday(new Date());
              user.setDesc("this is desc");
              map.addAttribute("user",user);
              users.add(user);
      
              User user2 = new User();
              user2.setName("lee");
              user2.setAge(20);
              user2.setPassword("1234");
              user2.setBirthday(new Date());
              user2.setDesc("this is desc");
              users.add(user2);
      
              User user3 = new User();
              user3.setName("susan");
              user3.setAge(20);
              user3.setPassword("1234");
              user3.setBirthday(new Date());
              user3.setDesc("this is desc");
              users.add(user3);
              System.out.println(users);
              map.addAttribute("userlist",users);
      
              return "thymeleaf/index";
          }
      
          @RequestMapping("thymeleaf/toContent")
          public String toContent(ModelMap map){
              map.addAttribute("name","jack");
              return "thymeleaf/content/content";
          }
      
          @PostMapping("th/postform")
          public String sendPost(User user){
              System.out.println(user.getName());
              return "redirect:/thymeleaf/index";
          }
      }
      

四.springboot异常处理

1.SpringBoot配置全局的异常捕获—web页面跳转

  • 页面跳转形式

    • 设置异常类用于模拟抛出异常

      //testException.java
      package com.example.demo2.controller;
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.GetMapping;
      @Controller
      public class testException {
          @GetMapping("/testexception")
          public void testExceptionMethod(){
              int i = 1/0;
          }
      }
      
    • 设置助手类(捕获异常的类)

      • 助手类需要用@ControllerAdvice注解,表示该类是用于捕获异常的类

      • 助手类中需要实现异常捕获的方法(使用@ExceptionHandle(value=Exception.class)注解修饰value表示捕获的异常类型,方法传入参数为request、response和exception)

      • 在方法中使用ModelAndView装载异常e,错误地址request.getRequestURL()和返回的页面

        //异常捕获类ExceptionHandler.java
        package com.example.demo2.exception;
        import org.springframework.web.bind.annotation.ControllerAdvice;
        import org.springframework.web.servlet.ModelAndView;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        
        @ControllerAdvice
        public class ExceptionHandler {
        
            @org.springframework.web.bind.annotation.ExceptionHandler(value = Exception.class)
            public ModelAndView errorException(HttpServletRequest request, HttpServletResponse response, Exception e){
                e.printStackTrace();
                ModelAndView mv = new ModelAndView();
                mv.addObject("exception",e);
                mv.addObject("url",request.getRequestURL());
                mv.setViewName("error");
                return mv;
            }
        }
        
      • 在templates中添加对应的返回页面,并在页面中使用el表达式获取对应的数据信息

        
        
        <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
        <head>
            <meta charset="UTF-8">
            <title>Titletitle>
        head>
        <body>
        <font color="red">异常处理页面font>
        <p th:text="${exception.message}">p>
        <p th:text="${url}">p>
        body>
        html>
        
  • ajax形式

    • 设置抛出异常的部分

      • 设置发起ajax请求的页面及对应的发起ajax请求的js代码

        
        
        <html lang="en" xmlns:th="http://www.springframework.org/schema/mvc">
        <head>
            <meta charset="UTF-8">
            <title>Titletitle>
            <script th:src="@{https://code.jquery.com/jquery-3.3.1.min.js}">script>
        head>
        <body>
        <script>
            $(function () {
                $.ajax({
                    type: "GET",
                    url: "/Test/tosendajaxerror",
                    success: function(data){
                        alert(data.info);
                    }
                });
            })
        script>
        body>
        html>
        
      • 设置服务端跳转和处理controller

        //testException.java
        package com.example.demo2.controller;
        import com.example.demo2.domain.Result;
        import org.springframework.stereotype.Controller;
        import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.ResponseBody;
        
        @Controller
        public class testException {
        
            @GetMapping("/testexception")
            public void testExceptionMethod(){
                int i = 1/0;
            }
        
            @GetMapping("/tosenderror")
            public String tosenderror(){
                return "thymeleaf/senderror";
            }
        
            @GetMapping("/tosendajaxerror")
            @ResponseBody
            public Result tosendajaxerror(){
                int i = 1/0;
                Result result = new Result();
                result.setStatus(200);
                result.setInfo("ok");
                return result;
            }
        }
        
    • 设置助手类(捕获异常的类)

      • 使用@RestControllerAdvice修饰类可以返回json对象

      • 其余内容与页面跳转形式一样

        //ajaxExceptionHandler.java
        package com.example.demo2.exception;
        import com.example.demo2.domain.Result;
        import org.springframework.web.bind.annotation.ExceptionHandler;
        import org.springframework.web.bind.annotation.RestControllerAdvice;
        
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        
        @RestControllerAdvice
        public class AjaxExceptionHandler {
        
            @ExceptionHandler(value = Exception.class)
            public Result ajaxExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception e){
                Result result = new Result();
                result.setStatus(555);
                result.setInfo(e.getMessage());
                return result;
            }
        
        }
        
  • 统一返回异常的形式

    • 添加对请求是否是ajax的判断方法

      //判断是否是ajax请求
      public static boolean isAjax(HttpServletRequest httpRequest){
          return (httpRequest.getHeader("X-Requested-With") != null && "XMLHttpRequest".equals(httpRequest.getHeader("X-Requested-With").toString()));
      }
      
    • 设置可以对ajax请求和页面请求同时处理的方法

      @org.springframework.web.bind.annotation.ExceptionHandler(value = Exception.class)
          public Object errorException(HttpServletRequest request, HttpServletResponse response, Exception e){
          e.printStackTrace();
          if(isAjax(request)){
              Result result = new Result();
              result.setStatus(555);
              result.setInfo(e.getMessage());
              return result;
          }else{
              ModelAndView mv = new ModelAndView();
              mv.addObject("exception",e);
              mv.addObject("url",request.getRequestURL());
              mv.setViewName("error");
              return mv;
          }
      }
      

五.Springboot整合Mybatis

  • 引入依赖

    
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>druidartifactId>
        <version>1.1.0version>
    dependency>
    
    <dependency>
    	<groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>5.1.41version>
    dependency>
    
    <dependency>
    	<groupId>org.mybatis.spring.bootgroupId>
        <artifactId>mybatis-spring-boot-starterartifactId>
        <version>RELEASEversion>
    dependency>
    
    <dependency>
    	<groupId>tk.mybatisgroupId>
        <artifactId>mapper-spring-boot-starterartifactId>
        <version>RELEASEversion>
    dependency>
    
    <dependency>
    	<groupId>com.github.pagehelpergroupId>
        <artifactId>pageholder-spring-boot-starterartifactId>
        <version>RELEASEversion>
    dependency>
    <dependency>
    	<groupId>com.alibabagroupId>
        <artifactId>druid-spring-boot-starterartifactId>
        <version>1.1.0version>
    dependency>
    <dependency>
    	<groupId>org.mybatis.generatorgroupId>
        <artifactId>mybatis-generator-coreartifactId>
        <version>1.3.2version>
    	<scope>compilescope>
        <optional>trueoptional>
    dependency>
    
  • 实现热部署,配置application.properties内容

    #为mybatis设置,生产环境可删除
    restart.include.mapper=/mapper-[\\w-\\.]+jar
    restart.include.pagehelper=/pagehelper-[\\w-\\.]+jar
    
  • 在application.properties中配置数据库相关信息(使用阿里巴巴的druid数据源)

    spring.datasource.url=jdbc:mysql://localhost:3306/testsource
    spring.datasource.username=root
    spring.datasource.password=123456
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.druid.initial-size = 1
    spring.datasource.druid.max-active = 20
    spring.datasource.druid.min-idle = 1
    spring.datasource.druid.test-on-borrow=true
    spring.datasource.druid.stat-view-servlet.allow=true
    
  • 在application.properties中配置mybatis/mapper/pagehelper

    #mybatis配置
    mybatis.type-aliases-package=com.learning.pojo
    mybatis.mapper-locations=classpath:mapper/*.xml
    
    #mapper
    #mappers 多个接口时逗号隔开
    mapper.mappers=com.learning.util.MyMapper
    mapper.not-empty=false
    mapper.identity=MYSQL
    
    #pagehelper分页插件配置
    pagehelper.helperDialect=mysql
    pagehelper.reasonable=true
    pagehelper.supportMethodsArguments=true
    pagehelper.params=count=countSql
    
  • generatorConfig.xml用于生成mapper文件,配置如下

    
    
    
    <generatorConfiguration>
        <context id="MysqlContext" targetRuntime="MyBatis3Simple" defaultModelType="flat">
            <property name="beginningDelimiter" value="`"/>
            <property name="endingDelimiter" value="`"/>
    
            <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
            	<property name="mappers" value="com.learning.utils.MyMapper">property>
            plugin>
    
            <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                            connectionURL="jdbc:mysql://localhost:3306/testsource"
                            userId="root"
                            password="123456">
            jdbcConnection>
    
            
            <javaModelGenerator targetPackage="com.learning.pojo" targetProject="src/main/java">javaModelGenerator>
    		
            <sqlMapGenerator targetPackage="mapper"  targetProject="src/main/resources"/>
    		
            <javaClientGenerator type="XMLMAPPER" targetPackage="com.learning.mapper"  targetProject="src/main/java"/>
    
            <table tableName="sys_user">table>
        context>
    generatorConfiguration>
    
  • 配置生成类

    package com.example.demo2;
    
    import org.mybatis.generator.api.MyBatisGenerator;
    import org.mybatis.generator.config.Configuration;
    import org.mybatis.generator.config.xml.ConfigurationParser;
    import org.mybatis.generator.internal.DefaultShellCallback;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;
    
    public class GeneratorDisplay {
    
        public void generator() throws Exception{
    
            List<String> warnings = new ArrayList<String>();
            boolean overwrite = true;
            //指定 逆向工程配置文件
            File configFile = new File("generatorConfig.xml");
            ConfigurationParser cp = new ConfigurationParser(warnings);
            Configuration config = cp.parseConfiguration(configFile);
            DefaultShellCallback callback = new DefaultShellCallback(overwrite);
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
                    callback, warnings);
            myBatisGenerator.generate(null);
    
        }
    
        public static void main(String[] args) throws Exception {
            try {
                GeneratorDisplay generatorSqlmap = new GeneratorDisplay();
                generatorSqlmap.generator();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }
    

1.使用generatorConfig生成mapper以及pojo

  • 运行生成类GeneratorDisplay.java

2.实现基于mybatis的CRUD功能

3.整合mybatis-pagehelper实现分页

4.自定义mapper的实现

未完待续…

你可能感兴趣的:(JAVA相关)