常用模板~~

常用模板

文章目录

1.java的HelloWord

public class Hello {
public static void main(String[] args) {

       System.out.println("Hello World 顺便测试中文乱码");

}
}

2.controller测试模板

2.1.返回json

2.2.返回页面

3.oracle分页模板

  • sql
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (

SELECT * FROM EMPLOY

) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21
  • mapper.xml模板
<select id="findByNameByPageObject"
		resultType="com.fcmap.ssm.domain.Demo">
		select * from(
		SELECT A.*, ROWNUM RN
		FROM (
		SELECT * FROM DEMO
		<where>
		<if test="name!=null and name!='' and name!='all'">
				and name like '%'||#{name}||'%'
			</if>
		</where>
		) A
		WHERE
		ROWNUM <![CDATA[ <= ]]>
		(#{pageIndex}*#{pageSize})
		)
		<where>
			RN <![CDATA[ >= ]]>
			((#{pageIndex}-1)*#{pageSize})+1
		</where>
	</select>

4.servlet模板

import java.io.IOException;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

/**

 *

 */

public class TestServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

       //>>处理POST请求参数乱码

       request.setCharacterEncoding("utf-8");

       //>>处理响应正文乱码

       response.setContentType("text/html;charset=utf-8");

       //TODO...


    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

       doGet(request, response);

    }

}

5.springboot.pom依赖模板(待补充)

<?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.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.hxh</groupId>
    <artifactId>basic_project</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>basic_project</name>
    <description>基础项目框架</description>

    <properties>
        <java.version>1.8</java.version>
        <swagger.version>2.9.2</swagger.version>
        <velocity.version>2.1</velocity.version>
        <mybatis-plus.version>3.1.2</mybatis-plus.version>
        <freemarker.version>2.3.28</freemarker.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--java制造假数据的工具类-->
        <dependency>
            <groupId>com.github.javafaker</groupId>
            <artifactId>javafaker</artifactId>
            <version>1.0.2</version>
        </dependency>
        <!-- springboot测试需要的注解 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 数据库生成模板的核心依赖 -->
        <dependency>
            <groupId>cn.smallbun.screw</groupId>
            <artifactId>screw-core</artifactId>
            <version>1.0.3</version>
        </dependency>
        <!-- 引入hutool工具类-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.4.4</version>
        </dependency>
        <!--引入google处理json数据的依赖-->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.2</version>
        </dependency>
        <!-- aop相关依赖 (@Aspect这个注解需要这个依赖) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <!-- 引入pagehlper分页插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.4</version>
        </dependency>
        <!--redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 热部署工具 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!-- mysql 驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- swagger ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger.version}</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger.version}</version>
        </dependency>

        <!-- mybatis_plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>

        <!-- 模板引擎 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>${velocity.version}</version>
        </dependency>

        <!-- 代码生成器 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>

        <!-- freemarker 模板引擎 -->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>${freemarker.version}</version>
        </dependency>

    </dependencies>

    <build>
        <finalName>BasicProject</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <!--  配置环境  -->
    <profiles>
        <profile>
            <!-- 开发 -->
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <activatedProperties>dev</activatedProperties>
            </properties>
        </profile>
        <profile>
            <!-- 测试 -->
            <id>test</id>
            <properties>
                <activatedProperties>test</activatedProperties>
            </properties>
        </profile>
        <profile>
            <!-- 准生产 -->
            <id>pre</id>
            <properties>
                <activatedProperties>pre</activatedProperties>
            </properties>
        </profile>
        <profile>
            <!-- 生产 -->
            <id>prod</id>
            <properties>
                <activatedProperties>prod</activatedProperties>
            </properties>
        </profile>
    </profiles>

</project>

6.mybatis的mapper.xml模板

<?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.fct.njjg.mapper.HlwjgJcssqdDao">

    <!-- 开启二级缓存 -->
    <cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.fct.njjg.pojo.entity.HlwjgJcssqd">
        <result column="RD" property="rd"/>
        <result column="DETAIL_CODE" property="detailCode"/>
        <result column="INVENTORY_CODE" property="inventoryCode"/>
        <result column="CREATE_DEPARTMENT_ID" property="createDepartmentId"/>
        <result column="JHPT_UPDATE_TIME" property="jhptUpdateTime"/>
        <result column="MATTER_CODE" property="matterCode"/>
        <result column="ORG_CODE" property="orgCode"/>
        <result column="ORG_NAME" property="orgName"/>
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        RD, DETAIL_CODE, INVENTORY_CODE, CREATE_DEPARTMENT_ID, JHPT_UPDATE_TIME, MATTER_CODE, ORG_CODE, ORG_NAME
    </sql>

</mapper>

7.vue单页面快速整合axios模板

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<!-- Bootstrap -->
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
	rel="stylesheet">
<script
	src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<script
	src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
<!-- 引入外部的css文件 -->
<link rel="stylesheet" type="text/css" href="css/emplist.css">

<!-- 引入vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<!-- 引入axios.js -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

</head>
<body>
	 <div id="app">
<!-- 把empList数组里面的数据显示,使用v-for -->
<hr>
<table class="table table-condensed">
<tr v-for="emp in empList">
<td>{{emp.id}}</td>
<td>{{emp.name}}</td>
<td>{{emp.job}} </td>
<td>{{emp.salary}}</td>
</tr>
</table>
<div v-for="emp in empList">
{{emp.id}}  =========> {{emp.name}}  --->{{emp.job}}  ---->{{emp.salary}}
</div>


    </div>
    
    <script>
        /**
         * axios发送ajax请求的步骤
         * 1.引入vue.js和axios.js这两个文件
         * 2.发送ajax请求
         */
        new Vue({
            el:'#app',
            //固定结构
            data:{ //在data定义变量和初始值
                //定义变量,值空数组
             empList:[]
            },
            created(){
                //页面渲染之前执行
                //调用定义的方法
                this.getempList()
            },
            methods:{//编写具体的方法
              //创建方法,查询所有用户数据
              getempList(){
                  //使用axios发送ajax请求
                  //axion.提交方式("请求接口路径").then(箭头函数).catch(箭头函数)
                  axios.get("http://rap2api.taobao.org/app/mock/261964/findall")
                  .then(response=>{
                      //console.log(response);
                      this.empList = response.data
                      console.log(this.empList)
                      
                  })
                  .catch(error=>{
                      console.log("axios发送ajax请求失败");
                  })
              }
            }
        })
    </script>
</body>
</html>

8.logback日志模板

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="FILE_ERROR_PATTERN"
              value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} %file:%line: %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
    <include
            resource="org/springframework/boot/logging/logback/defaults.xml" />
    <appender name="CONSOLE"
              class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
        </filter>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <appender name="FILE_INFO"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--如果只是想要 Info 级别的日志,只是过滤 info 还是会输出 Error 日志,因为 Error 的级别高, 所以我们使用下面的策略,可以避免输出
            Error 的日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!--过滤 Error -->
            <level>ERROR</level>
            <!--匹配到就禁止 -->
            <onMatch>DENY</onMatch>
            <!--没有匹配到就允许 -->
            <onMismatch>ACCEPT</onMismatch>
        </filter>
        <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File>
            的日志都是当天的。 -->
        <!--<File>logs/info.spring-boot-demo-logback.log</File> -->
        <!--滚动策略,按照时间滚动 TimeBasedRollingPolicy -->
        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间 -->
            <FileNamePattern>logs/info.created_on_%d{yyyy-MM-dd}.part_%i.log</FileNamePattern>
            <!--只保留最近90天的日志 -->
            <maxHistory>90</maxHistory>
            <!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志 -->
            <!--<totalSizeCap>1GB</totalSizeCap> -->
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- maxFileSize:这是活动文件的大小,默认值是10MB,本篇设置为1KB,只是为了演示 -->
                <maxFileSize>2MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!--<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> -->
        <!--<maxFileSize>1KB</maxFileSize> -->
        <!--</triggeringPolicy> -->
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
    </appender>

    <appender name="FILE_ERROR"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--如果只是想要 Error 级别的日志,那么需要过滤一下,默认是 info 级别的,ThresholdFilter -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>Error</level>
        </filter>
        <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File>
            的日志都是当天的。 -->
        <!--<File>logs/error.spring-boot-demo-logback.log</File> -->
        <!--滚动策略,按照时间滚动 TimeBasedRollingPolicy -->
        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间 -->
            <FileNamePattern>logs/error.created_on_%d{yyyy-MM-dd}.part_%i.log</FileNamePattern>
            <!--只保留最近90天的日志 -->
            <maxHistory>90</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- maxFileSize:这是活动文件的大小,默认值是10MB,本篇设置为1KB,只是为了演示 -->
                <maxFileSize>2MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>${FILE_ERROR_PATTERN}</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE_INFO" />
        <appender-ref ref="FILE_ERROR" />
    </root>
</configuration>

9.js的单击事件alert的Helloworld

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<button id="btn"></button>
<script>
function f1(){
	alert("hello world");
}
document.getElementById("btn").onclick=f1
</script>
</body>
</html>

10.jQuery的单击事件alert的Helloworld

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--引入jQuery-->
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<button id="btn1">我是一个按钮(测试公用的jQuery库是否引入成功)</button>
<script>
    $(function(){
        $("#btn1").click(function(){
            alert("hello jQuery ");
        });
    });
</script>
</body>
</html>

11.springboot的yml模板(ssm+redis)

server:
  port: 8086
  servlet:
    context-path: /
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
#    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/yonghedb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false
    username: root
    password: root
    
  #springboot整合redis的配置模板
 redis:
    database: 0
    host: localhost
    port: 6379
    password:
    #支持另外两种请求方式,就是一共支持四种请求方式
  mvc:
     hiddenmethod:
        filter:
           enabled: true
           
           
           
  #跳转页面需要配置视图解析器
  thymeleaf:         #引入mvn配置
      prefix: classpath:/templates/pages/     # /默认代表根目录 src/main/webapp
      suffix: .html
      mode: LEGACYHTML5
      


#spring整合Mybatis-plus
mybatis:
    #定义别名包
  type-aliases-package: com.shaoming.entity
    #加载mapper映射文件
  mapper-locations: classpath:/mappers/*.xml
    #开启驼峰映射
  configuration:
    map-underscore-to-camel-case: true
    


#添加mybatis的sql日志
logging:
  level:
     com.shaoming.dao: debug

12.Thmeleaf模板(循环遍历)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap 101 Template</title>
    <!-- Bootstrap -->
    <link
            href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
            rel="stylesheet">
    <script
            src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
    <script
            src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
    <style type="text/css">
        #div2{
            text-align: center;
            border: 3px solid red;
        }
        a{
            font-size: 25px;
        }
    </style>
</head>
<body>
<!-- 查询所有员工列表页面 -->
<h1 align="center">员工列表信息</h1>
<!-- 这个表格示显示员工数据的 -->
<div align="center"><a th:href="@{/emp_add}">添加员工信息</a></div>
<div id="div2">
    <table class="table table-condensed">
        <thead>
        <tr>
            <td>编号</td>
            <td>ID</td>
            <td>NAME</td>
            <td>JOB</td>
            <td>SALARY</td>
            <td>OPTENTATION(操作)</td>
        </thead>
        <tbody>
        <tr th:each="emp,varstatus:${emps}">
            <td th:text="${varstatus.count}"></td>
            <td th:text="${emp.id}"></td>
            <td th:text="${emp.name}"></td>
            <td th:text="${emp.job}"></td>
            <td th:text="${emp.salary}"></td>
            <td>
                <a th:href="@{/toupdate(id=${emp.id})}">修改</a>
                &nbsp;
                &nbsp;
                <a th:href="@{/deleteById(id=${emp.id})}">删除</a>
            </td>
        </tr>
        </tbody>
    </table>
</div>
</body>
</html>

13.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>
<style type="text/css">
/* 这里可以书写css样式 */
table {
    border: 2px solid red;
    /* 设置表格的边框和单元格的边框合并 */
    border-collapse: collapse;
    /* 设置当前元素的左右编剧自适应,即设置
当前元素水平方向居中
*/
    margin-left: auto;
    margin-right: auto;
    /* 设置背景颜色 */
    background: lightgrey;
}


td, th {
    border: 2px solid red;
    /* 设置单元格边框和内容之间的距离 */
    padding: 5px;
}


h1 {
    /* 让当前元素的内容居中显示 */
    text-align: center;
}


div {
    text-align: center;
}


a {
    color: orange;
}
#ad{
color: red;
}
</style>
<title>您好Springboot</title>
</head>
<body>
    <div>
        <a href="${ pageContext.request.contextPath }/emp/emp_insert">添加</a>
    </div>
    <hr>
    <table>
        <thead>
            <tr>
                <th>编号</th>
                <th>id</th>
                <th>名字</th>
                <th>工作</th>
                <th>薪资</th>
                <th>操作</th>
            </tr>
            <c:forEach items="${ emps }" var="emp" varStatus="state">
                <tr>
                    <td>${ state.count }</td>
                    <td>${ emp.id }</td>
                    <td>${ emp.getName() }</td>
                    <td>${ emp.job }</td>
                    <td>${ emp.salary }</td>
                    <td align="center">
                    <a id="ad" href="${ pageContext.request.contextPath }/emp/deletebyid?id=${ emp.id}">删除</a>
                    &nbsp;&nbsp;|&nbsp;&nbsp;
                    <a id="au" href="${ pageContext.request.contextPath }/emp/selectbyid?id=${ emp.id }">修改</a>
                    </td>
                </tr>
            </c:forEach>
    </table>
</body>
</html>

14.bootstrap快速开始模板

14.1.使用cdn的方式引入bootstrap

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap 101 Template</title>
    <!-- Bootstrap -->
    <link  href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"  rel="stylesheet">
    <script  src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
    <script  src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
    
  </head>
  <body>
    <h1>你好,世界!</h1>
   
   
  </body>
</html>

14.2.使用本地文件方式引入bootstrap

<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap 101 Template</title>
    <!-- Bootstrap -->
    <link  href="./css/bootstrap.min.css"  rel="stylesheet">
    <script  src="./js/bootstrap.min.js"></script>
    
  </head>
  <body>
    <h1>你好,世界!</h1>
   
   
  </body>
</html>

说明:

说明:

这种方式是从官网下载bootstrap的js和css

然后放到springboot的static目录下

15.ssm种dao层测试模板

重点说明

首先要在spring配置文件中添加如下配置,否则测试混滚的事务不会生效

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

/**
* 测试dao层
* @author Admin
*
*/
@ContextConfiguration("classpath:/spring-mybatis.xml")
@RunWith(SpringJUnit4ClassRunner.class)
//这里可以声明一个事务管理 每个单元测试都进行事务回滚  无论成功与否  
@TransactionConfiguration(defaultRollback =  true)  
@Transactional
public class DemoDaoTest {
    @Autowired
    private DemoDao demoDao;
    /**
     * 测试查询所有
     */
    //@Rollback(false)  这个是不会滚,这个是提交
    //不设置就是回滚
    //设置@Rollback也是回滚
    @Test
    public void testFindAll() {
        List<Demo> demoList = demoDao.findAll();
        demoList.forEach(System.out::println);
    }

16.springboot项目中全局跨域配置类

说明:

springboot处理跨域请求的方式

1.在Controller类上加注解

@CrossOrigin

2.配置类:如下


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
   springboot处理跨域请求的注解
 * 处理跨域请求
 * @author ydb
 * @date 2020/10/19 10:04
 */
@Configuration
public class CorsConfig {
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");// 1允许任何域名使用
        corsConfiguration.addAllowedHeader("*");// 2允许任何头
        corsConfiguration.addAllowedMethod("*"); // 3允许任何方法(post、get等)
        return corsConfiguration;
    }
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }
}

17.springboot全局时间格式处理配置类

/**
 * 全局日期格式化
 */
@JsonComponent
public class DateFormatConfig {

    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 日期格式化
     */
    public static class DateJsonSerializer extends JsonSerializer<Date> {
        @Override
        public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeString(dateFormat.format(date));
        }
    }

    /**
     * 解析日期字符串
     */
    public static class DateJsonDeserializer extends JsonDeserializer<Date> {
        @Override
        public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
            try {
                return dateFormat.parse(jsonParser.getText());
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }

        }
    }
}

18.springboot使用redis整合session共享的配置类


@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class SessionConfig {
 
}

19.springboot整合swagger配置类


@Configuration
@EnableSwagger2 // 标记项目启用 Swagger API 接口文档
public class SwaggerConfiguration {
 
    @Bean
    public Docket createRestApi() {
        // 创建 Docket 对象
        return new Docket(DocumentationType.SWAGGER_2) // 文档类型,使用 Swagger2
                .apiInfo(this.apiInfo()) // 设置 API 信息
                // 扫描 Controller 包路径,获得 API 接口
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.fct.controller"))
                .paths(PathSelectors.any())
                // 构建出 Docket 对象
                .build();
    }
 
    /**
     * 创建 API 信息
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("设置主题")
                .description("我是一段描述")
                .version("1.0.0") // 版本号
                .build();
    }
 
}
 

20.springboot中拦截器使用模板

拦截器配置模板

package com.shaoming.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Auther: shaoming
 * @Date: 2020/12/31 14:02
 * @Description:
 */
@Component
public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器preHandle");

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                Exception ex) throws Exception {
        System.out.println("拦截器afterCompletion");
    }
}

拦截器注入模板

package com.shaoming.config;

import com.shaoming.interceptor.MyInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @Auther: shaoming
 * @Date: 2020/12/31 14:07
 * @Description:
 * 拦截器配置
 */
@Configuration
public class MyInterceptorConfig implements WebMvcConfigurer {
    @Autowired
    private MyInterceptor myInterceptor;
    /**
     * 拦截器注册
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor);
        /**
         *  registry.addInterceptor(new LoginInterceptor())
         *                 // addPathPatterns 用于添加拦截规则
         *                 .addPathPatterns("/**")
         *                 .excludePathPatterns("/swagger-ui.html")
         *                 .excludePathPatterns("/swagger-resources/**")
         *                 .excludePathPatterns("/error")
         *                 .excludePathPatterns("/webjars/**");
         *         WebMvcConfigurer.super.addInterceptors(registry);
         */
    }
}

21.springboot中过滤器使用模板

过滤器配置模板

package com.shaoming.filter;

import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Auther: shaoming
 * @Date: 2020/12/31 14:04
 * @Description: 自定义过滤器
 */
@Component
public class MyFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        System.out.println("filter执行前");
        filterChain.doFilter(httpServletRequest,httpServletResponse);
        System.out.println("filter执行后");
    }
}



过滤器注册使用模板

package com.shaoming.config;

import com.shaoming.filter.MyFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Configuration;

/**
 * @Auther: shaoming
 * @Date: 2020/12/31 14:09
 * @Description:
 */
@Configuration
public class MyFilterConfig {
    @Autowired
    private MyFilter myFilter;
    public FilterRegistrationBean getMyFilter(){
         FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
         filterRegistrationBean.setFilter(myFilter);
         filterRegistrationBean.addUrlPatterns("/*");
         filterRegistrationBean.setOrder(1);
         return filterRegistrationBean;
    }
}

21.文件上传

单文件上传

springboot配置文件

spring.servlet.multipart.max-file-size=2MB
spring.servlet.multipart.max-request-size=2MB
file.upload.path=G:/testfile/
# file.upload.path=/Users/didi/   #mac系统的路径
# file.upload.path=/opt/myfile/    #linux系统路径

html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/需要上传的文件地址" method="post" enctype="multipart/form-data">
    <input type="file" name="fileupload">
    <input type="submit" value="上传">
</form>
</body>
</html>

controller

@Slf4j
@Controller
public class UploadController {

    @Value("${file.upload.path}")
    private String path;

    @GetMapping("/")
    public String uploadPage() {
        return "upload";
    }

    @PostMapping("/upload")
    @ResponseBody
    public String create(@RequestPart MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        String filePath = path + fileName;

        File dest = new File(filePath);
        Files.copy(file.getInputStream(), dest.toPath());
        return "Upload file success : " + dest.getAbsolutePath();
    }

}

多文件上传

springboot配置文件同上

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>多文件上传页面</title>
</head>
<body>
<h1 style="text-align: center;color: royalblue">测试多文件上传的页面</h1>
<!--
文件上传的要素
1.表单是post请求
2.input的type时file类型
3.表单声明数据类型 enctype="multipart/form-data">
-->
<form action="/uploadfiles" method="post" enctype="multipart/form-data">
    文件1:<input type="file" name="files"/>
    <br data-tomark-pass>
    文件2:<input type="file" name="files"/>
    <br data-tomark-pass>
    <hr>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

controller

package com.shaoming.controller;


import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import java.nio.file.Files;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;

/**
 * @Auther: shaoming
 * @Date: 2021/1/8 10:53
 * @Description:
 */
@Controller
@Api(tags = "测试多文件上传")
public class FilesController {
    @Value("${file.upload.path}")
    private String path;

    @GetMapping("/uploads")//get请求
    @ApiOperation(value = "跳转到多文件上传页面", notes = "测试多文件上传", httpMethod = "")
    public String toUploadManyFiles(HttpServletRequest request) {
        return "uploads";
    }

    @PostMapping("uploadfiles")//请求方式
    @ResponseBody
    @ApiOperation(value = "多文件上传", notes = "测试多文件上传", httpMethod = "")//swagger方法注解
    public String uploadFiles(@RequestPart MultipartFile[] files) throws IOException {
        StringBuffer message = new StringBuffer();
        for (MultipartFile file : files) {
            String fileName = file.getOriginalFilename();
            String filePath = path + fileName;
            File dest = new File(filePath);
            Files.copy(file.getInputStream(), dest.toPath());
            message.append("Upload file success : " + dest.getAbsolutePath()).append("<br>");
        }
        return message.toString();
    }
}

ajax单文件上传

springboot配置文件同上

html

<!DOCTYPE html>
<html lang="en">
<script src="../js/jquery-1.8.3.min.js"></script>

<head>
    <meta charset="UTF-8">
    <title>静态页面-ajax上传</title>

</head>
<body>
<div id="result"></div>
<input type="file" id="file">
<input type="button" value="上传" onclick="uploadFile()">
<script>
    function uploadFile() {
        var file = $("#file")[0].files[0];
        var formData = new FormData();
        formData.append("file",file);
        $.ajax({
            type:'post',
            url:'/upload',
            processData:false,
            contentType:false,
            data:formData,
            success:function(msg) {
                alert("sb")
                $('#result').html(msg)
            }
        })
    }
</script>

</body>
</html>

controller

  @PostMapping("/upload")//请求方式
    @ResponseBody
    @ApiOperation(value = "文件上传", notes = "", httpMethod = "")//swagger方法注解
    public String upload(@RequestPart MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        String filePath = path + fileName;
        File dest = new File(filePath);
        Files.copy(file.getInputStream(), dest.toPath());
        return "Upload file success : " + dest.getAbsolutePath();
    }

    /**
     * ajax文件上传
     */
    @GetMapping("/ajaxupload")//get请求
    @ApiOperation(value = "ajax文件上传页面", notes = "", httpMethod = "")
    public String ajaxuploadHtml() {
        return "ajax";
    }

22.jQuery的ajax模板

  • ajax通用模板方法
$.ajax({
        url : "userList.json",//请求的url
        method : "GET",//请求的方式
        contentType: "application/json",//请求数据为json格式
        data : null,//请求的参数
        async : true,//默认为true,表示异步请求
        dataType : "text",//返回的数据时json格式的对象,如果是字符窜,简单类型一般就是text类型
        success : function(data){
            console.log(data);
        },//定义成功的回调函数
        error : function() {
            alert("ajax请求失败");
        }//失败的回调函数
    });
  • get方法
  • post方法
  • getJson方法

23.VO类的模板

Msg(借见的vo类)

package com.fct.njjg.model.vo;

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

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel("视图返回对象,jsonresult")
public class Msg {
	// 状态码 100 成功 200 失败
	@ApiModelProperty(value = "响应码")
	private int code;
	// 提示信息
	@ApiModelProperty(value = "提示信息")
	private String msg;
	// 用户要返回给客户端的数据
	@ApiModelProperty(value = "数据信息")
	private Map<String, Object> data = new HashMap<String, Object>();

	// 当前对象添加用户要返回给客户端的数据
	public Msg add(String key, Object value) {
		this.getData().put(key, value);
		return this;
	}

	// 执行成功
	public static Msg success() {
		Msg result = new Msg();
		result.setCode(100);
		result.setMsg("执行成功!");
		return result;
	}

	// 执行失败
	public static Msg fail() {
		Msg result = new Msg();
		result.setCode(200);
		result.setMsg("执行失败!");
		return result;
	}

	public int getCode() {
		return code;
	}

	public void setCode(int code) {
		this.code = code;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public Map<String, Object> getData() {
		return data;
	}

	public void setData(Map<String, Object> data) {
		this.data = data;
	}
}

R(人人开源项目的vo类)

package com.ckf.springbootswagger.pojo;


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

/**
 * 返回数据
 *
 * @author Mark sunlightcs@gmail.com
 */
public class R extends HashMap<String, Object> {
    private static final long serialVersionUID = 1L;
//    private Integer code;
//    private String msg;
//    private Object data;
    public R() {
        put("code", 0);
    }

    public static R error() {
        return error(500, "未知异常,请联系管理员");
    }

    public static R error(String msg) {
        return error(500, msg);
    }

    public static R error(int code, String msg) {
        R r = new R();
        r.put("code", code);
        r.put("msg", msg);
        return r;
    }

    public static R ok(String msg) {
        R r = new R();
        r.put("msg", msg);
        return r;
    }

    public static R ok(Map<String, Object> map) {
        R r = new R();
        r.putAll(map);
        return r;
    }

    public static R ok() {
        return new R();
    }

    public R put(String key, Object value) {
        super.put(key, value);
        return this;
    }
}

24.Mybatis-plus逆向工程的模板

那日志记录表为例

package com.fct.njjg.pojo.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import java.time.LocalDate;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import java.sql.Clob;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * <p>
 * 日志记录表
 * </p>
 *
 * @author shaoming
 * @since 2020-11-05
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("SYS_INFO_LOG")
@ApiModel(value="SysInfoLog对象", description="日志记录表")
public class SysInfoLog extends Model<SysInfoLog> {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键ID")
    @TableId(value = "OPER_ID", type = IdType.NONE)
    private String operId;

    @ApiModelProperty(value = "功能模块")
    @TableField("OPER_MODUL")
    private String operModul;

    @ApiModelProperty(value = "操作类型")
    @TableField("OPER_TYPE")
    private String operType;

    @ApiModelProperty(value = "操作描述")
    @TableField("OPER_DESC")
    private String operDesc;

    @ApiModelProperty(value = "请求参数")
    @TableField("OPER_REQU_PARAM")
    private Clob operRequParam;

    @ApiModelProperty(value = "返回参数")
    @TableField("OPER_RESP_PARAM")
    private Clob operRespParam;

    @ApiModelProperty(value = "操作员ID")
    @TableField("OPER_USER_ID")
    private String operUserId;

    @ApiModelProperty(value = "操作原名称")
    @TableField("OPER_USER_NAME")
    private String operUserName;

    @ApiModelProperty(value = "操作方法")
    @TableField("OPER_METHOD")
    private String operMethod;

    @ApiModelProperty(value = "请求URI")
    @TableField("OPER_URI")
    private String operUri;

    @ApiModelProperty(value = "请求IP")
    @TableField("OPER_IP")
    private String operIp;

    @ApiModelProperty(value = "操作时间")
    @TableField("OPER_CREATE_TIME")
    private LocalDate operCreateTime;

    @ApiModelProperty(value = "操作版本号")
    @TableField("OPER_VAR")
    private String operVar;


    @Override
    protected Serializable pkVal() {
        return this.operId;
    }

}


详细版本实体类模板

package com.example.demo.model.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

/**
 * @author shaoming
 * @Date: 2021/3/30 01:57
 * @Description:实体类(user)
 */

/**
 * lombok注解
 * @Data 自动生成get/set/toString/hashcode/equals方法
 * @AllArgsConstructor 自动为实体类生成全参数的构造器
 * @NoArgsConstructor 自动实体类生成无参数构造器
 * @Accessors(chain = true) 表示支持来链式加载
 * @EqualsAndHashCode(callSuper = false)
 * EqualsAndHashCode实则就是在比较两个对象的属性;
 * 当@EqualsAndHashCode(callSuper = false)时不会比较其继承的父类的属性可能会导致错误判断;
 * 当@EqualsAndHashCode(callSuper = true)时会比较其继承的父类的属性;
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
/**
 * @TableName
 * 声明实体类对应数据库的表名
 */
@TableName(value = "user")
/**
 * @ApiModel
 * swagger实体类的注解,一般vlue是  类型对象
 * description一般可以设置为表注释
 */
@ApiModel(value = "User对象",description = "对应数据库表名")
public class User extends Model<User> {
    /**
     * 如果在SpringBoot配置文件配置
     * mybatis-plus.global-config.db-config.id-type=auto
     * 那么实体类对应主键的属性不需要再声明为主键自增
     * 重点说明:
     * 如果指定为主键自增,那么需要在创建数据表的时候设置主键自增
     * 说明:
     * MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法)
     * 雪花算法是由Twitter公布的分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的主键的有序性
     */
//    @TableId(type = IdType.AUTO)//声明为主键,主键生成方式为主键自增
    /**
     * @ApiModelProperty
     * 这个注解是swagger实体类属性注解,一般可以是数据库字段的注释
     * example是示例的数据
     */
    @ApiModelProperty(value = "主键ID",example = "1",notes = "主键id的描述信息")
    private Long id;
    @TableField(value = "name")
    @ApiModelProperty(value = "姓名",example = "root",notes = "主键id的描述信息")
    private String name;
    @TableField(value = "age")
    @ApiModelProperty(value = "年龄",example = "18",notes = "用户的年龄")
    private Integer age;
    @TableField(value = "email")
    @ApiModelProperty(value = "邮箱",example = "1025378286@qq.com",notes = "用户的邮箱")
    private String email;
}

dao层接口

package com.fct.njjg.mapper;

import com.fct.njjg.pojo.entity.SysInfoLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * <p>
 * 日志记录表 Mapper 接口
 * </p>
 *
 * @author shaoming
 * @since 2020-11-05
 */
public interface SysInfoLogDao extends BaseMapper<SysInfoLog> {

}

service层接口

package com.fct.njjg.service;

        import com.fct.njjg.pojo.entity.SysInfoLog;
        import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 * 日志记录表 服务类
 * </p>
 *
 * @author shaoming
 * @since 2020-11-05
 */
public interface SysInfoLogService extends IService<SysInfoLog> {

}

service实现类

package com.fct.njjg.service.impl;

import com.fct.njjg.pojo.entity.SysInfoLog;
import com.fct.njjg.mapper.SysInfoLogDao;
import com.fct.njjg.service.SysInfoLogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 日志记录表 服务实现类
 * </p>
 *
 * @author shaoming
 * @since 2020-11-05
 */
@Service
public class SysInfoLogServiceImpl extends ServiceImpl<SysInfoLogDao, SysInfoLog> implements SysInfoLogService {

}

controller

package com.fct.njjg.controller;


import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 * 日志记录表 前端控制器
 * </p>
 *
 * @author shaoming
 * @since 2020-11-05
 */
@RestController
@RequestMapping("/sysInfoLog")
public class SysInfoLogController {

}

25.AOP切面模板

execution表达式

切入点表达式写法:
  参数包括:execution("修饰符 返回值类型 包.类.方法名(参数..) throws异常")

  修饰符(举例):一般省略

     *       任意

    public     公共访问

  返回值(举例):

    void       无返回值

    String      返回值是字符串类型

    *       返回值任意

  包(举例):      

    com.xx.user.dao    固定包

    com.xx.*.dao          com.xx下的任意包中的dao包

    com.xx.user.dao..  包括dao下所有子包中

  类(举例):

    UserDaoImpl   具体类

    User*         以User开头类

    *User         以User结尾类

    *           任意类

  方法(举例):

    addUser      具体方法

    *        任意方法

    *User      以add结尾方法

    add*       以add开头方法

  参数(无参):

    ()         无参

    (..)       任意参数

    (String,int)     1String1int类型的参数

    (int)        1int类型参数

  throws,可省略一般不写

切面

package com.shaoming.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

import java.lang.reflect.Method;
import java.util.Arrays;

import static java.util.Arrays.*;

/**
 * @Auther: shaoming
 * @Date: 2020/12/31 15:58
 * @Description:
 */
@Order(value = 2)//这个注解表示切面的优先级,数字越小,优先级越大
@Aspect//这个注解表示这个类是一个aop切面
@Component//切面必须交给spring容器管理
public class AopExecution {
    @Pointcut("execution(public String com.shaoming.service.MyService.*(String))")
    public void point(){
        System.out.println("切入点方法的内容不会执行");
    }
    @Before(value = "point()")
    public void doBefore(JoinPoint joinPoint){
         System.out.println("前置通知:"+joinPoint);
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        System.out.println("获取请求的类名(去类名:包名+类名)"+joinPoint.getTarget().getClass().getName());
        System.out.println("获取方法名的全路径(包名+类名+方法名):"+joinPoint.getTarget().getClass().getName() + "." + signature.getMethod().getName().toString());
        System.out.println("获取的方法名称:"+signature.getMethod().getName().toString());
        System.out.println("获取参数的名称"+ asList(signature.getParameterNames()));
        System.out.println("获取参数的类型"+ asList(signature.getParameterTypes()));
        System.out.println("获取方法的返回值的类型:"+signature.getReturnType().toString());
    }
    @After(value = "point()")
    public void doAfter(JoinPoint joinPoint){
        System.out.println("后置通知" + joinPoint);
    }
    @AfterReturning(value = "point()",returning = "res")
    public void doAfterReturning(JoinPoint joinPoint,Object res){
        System.out.println("返回通知" + joinPoint);
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        System.out.println("====返回通知===获取方法名称"+signature.getMethod().getName());
        System.out.println("=====返回通知====获取方法返回值的类型"+signature.getMethod().getReturnType().toString());
        System.out.println("=====返回通知中获取方法的返回值:\t" + res);
    }
    @AfterThrowing(value = "point()",throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint,Exception e){
        System.out.println("异常通知:"+joinPoint);
        System.out.println("======异常通知===异常信息为:"+e.getMessage());
    }
    @Around(value = "point()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("=============环绕通知的操作开始获取一些信息================");
        System.out.println("环绕通知:" + proceedingJoinPoint);
        Object proceed = null;
        try {
           proceed = proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("=======环绕通知=====获取异常信息为:"+throwable.getMessage());
        }
         MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();

        System.out.println("======环绕通知====获取请求的类名(去类名:包名+类名)"+proceedingJoinPoint.getTarget().getClass().getName());
        System.out.println("======环绕通知====获取方法名的全路径(包名+类名+方法名):"+proceedingJoinPoint.getTarget().getClass().getName() + "." + signature.getMethod().getName().toString());
        System.out.println("======环绕通知====获取的方法名称:"+signature.getMethod().getName().toString());
        System.out.println("======环绕通知====获取参数的名称"+ asList(signature.getParameterNames()));
        System.out.println("======环绕通知====获取参数的类型"+ asList(signature.getParameterTypes()));
        System.out.println("======环绕通知====获取方法的返回值的类型:"+signature.getReturnType().toString());
        return proceed;
    }

}

25.mybatis-plus方法使用示例

数据库脚本

xxxxxxxxxx 1DROP TABLE IF EXISTS `user`;2CREATE TABLE `user` (3  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',4  `name` varchar(80) DEFAULT NULL COMMENT '用户名',5  `password` varchar(40) DEFAULT NULL COMMENT '用户密码',6  PRIMARY KEY (`id`)7) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

实体类

@Data
@Accessors(chain=true)
public class User {
    private String id;
    private String name;
    private String password;
}
package com.shaoming;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shaoming.mapper.UserMapper;
import com.shaoming.model.entity.User;
import com.shaoming.service.IUserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Calendar;
import java.util.List;

@SpringBootTest
class SpringbootTestDemoApplicationTests {
@Autowired
private IUserService iUserService;
@Autowired
private UserMapper userMapper;
    @Test
    void contextLoads() {
    }

    /**
     * 查询所有
     */
    @Test
    public void testMapper1(){
        List<User> users = userMapper.selectList(null);
        System.out.println(users);
    }
    @Test
    public void testService1(){
        List<User> list = iUserService.list(null);
        System.out.println(list);
    }

    /**
     * 按id查询
     */
    @Test
    public void testMapperSelectById(){
        User user = userMapper.selectById(1);
        System.out.println(user);
    }

    @Test
    public void testServiceSelectById(){
        User user = iUserService.getById(1);
        System.out.println(user);
    }

    /**
     * 新增
     */
    @Test
    public void testMapperInsert(){
        for(int i=0 ; i<10 ; i++){
        User user = new User();
        user.setId(null).setName("root"+i).setPassword("root"+i);
        userMapper.insert(user);
        }
    }
    @Test
    public void testServiceInsert(){
        for(int i=0 ; i<10 ; i++){
        User user = new User();
        user.setId(null).setName("root"+i).setPassword("root"+i);
            iUserService.save(user);
        }
    }

    /**
     * 更新
     */
    @Test
    public void testMapperUpdataById(){
        User user = new User();
        user.setId("10").setName("root1010").setPassword("root101010");
        userMapper.updateById(user);
    }

    @Test
    public void testServiceUpdateById(){
        User user = new User();
        user.setId("10").setName("root1010").setPassword("root101010");
        iUserService.updateById(user);
    }

    /**
     * 根据条件查询集合
     * MariaDB [jwt]> select * from user where name = 'root1' and password='root1';
     * +----+-------+----------+
     * | id | name  | password |
     * +----+-------+----------+
     * |  2 | root1 | root1    |
     * | 11 | root1 | root1    |
     * +----+-------+----------+
     * 2 rows in set (0.000 sec)
     */
    @Test
    public void testMapperSelectByParam(){
        /**
         * 报错
         * TooManyResultsException
         * 因为查询结果不止一条记录
         */
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
//        userQueryWrapper.eq("name","root1");//报错,因为root1的记录是两个
        userQueryWrapper.eq("name","root2");
        System.out.println(userMapper.selectOne(userQueryWrapper));
    }
    @Test
    public void testMapperSelectListByParam(){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("name","root1");
        userQueryWrapper.eq("password","root1");
        System.out.println(userMapper.selectList(userQueryWrapper));
    }

    @Test
    public void testServiceSelectByParam(){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("name","root1");//报错,因为root1的记录是两个
//        userQueryWrapper.eq("name","root2");
        System.out.println(iUserService.getOne(userQueryWrapper));
    }
    @Test
    public void testServiceSelectListByParam(){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("name","root1");
        userQueryWrapper.eq("password","root1");
        System.out.println(iUserService.list(userQueryWrapper));
    }

     
}

26.mybatis特殊字符转义

<<小于号
>>大于号
&&
单引号
"双引号

总结整理

   &							&amp;		
     <							&lt;
	 >							&gt;
	 "							&quot;  //双引号
     '							&apos;  //单引号
   a<=b                 	a &lt;=b 或者 a <![CDATA[<= ]]>b 
   a>=b                 	a &gt;=b 或者 a <![CDATA[>= ]]>b
   a!=b						a <![CDATA[ <> ]]>b 或者 a <![CDATA[!= ]]>b

27.文件下载模板

package com.shaoming.controller;
 
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URLEncoder;
 
/**
 * @Auther: shaoming
 * @Date: 2021/1/11 13:50
 * @Description:
   文件下载测试
 */
@Controller
@Slf4j
@Api(tags = "文件下载")
public class FileController {
//@Value注解是引用springboot配置文件的参数
    @Value("${local.path}")
    private String path;
 
    /**
     * 文件下载
     */
    @GetMapping("download")
    @ApiOperation(value = "springboot项目static目录文件下载", notes = "", httpMethod = "")
    public void download(String fileName, HttpServletResponse response)  throws Exception
    {
        //根据文件名去指定目录中查找文件(去springoot默认的static目录下载资源)
        String realPath = ResourceUtils.getURL("classpath:").getPath() + "static/files" ;
        //获取服务器的路径,如果服务器是windows
//        String realPath = "g:/";
        //读取文件
        File file = new File(realPath, fileName);
        //获取文件输入流
        FileInputStream is = new FileInputStream(file);
        //attachment; 附件下载   inline 在线打开(图片 pdf )
        response.setHeader("content-disposition","attachment;fileName="+fileName);
        //获取响应输出流
        ServletOutputStream os = response.getOutputStream();
        //文件拷贝
        IOUtils.copy(is,os);
 
        //关流方式(优雅)
        IOUtils.closeQuietly(is);
        IOUtils.closeQuietly(os);
    }
    @GetMapping("localdownload")
    @ApiOperation(value = "服务器路径文件下载", notes = "", httpMethod = "")
    public void localdownload(String fileName, HttpServletResponse response)  throws Exception
    {
        //根据文件名去指定目录中查找文件(去springoot默认的static目录下载资源)
//        String realPath = ResourceUtils.getURL("classpath:").getPath() + "static/files" ;
        //服务器的路径
        String realPath = path;
        //读取文件
        File file = new File(realPath, fileName);
        //获取文件输入流
        FileInputStream is = new FileInputStream(file);
        //attachment; 附件下载   inline 在线打开(图片 pdf )
        /**
         * 这种方式设置会有中文乱码
         */
//        response.setHeader("content-disposition","attachment;fileName="+fileName);
        /**
         * 解决文件名中文乱码的问题
         */
        response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));
        /**
         * 设置强制下载不打开
         */
        response.setContentType("application/force-download");// 设置强制下载不打开
        //获取响应输出流
        ServletOutputStream os = response.getOutputStream();
        //文件拷贝
        IOUtils.copy(is,os);
 
        //关流方式(优雅)
        IOUtils.closeQuietly(is);
        IOUtils.closeQuietly(os);
    }
}

28.springboot排除拦截静态资源模板

一般拦截器模板

package com.lzk.config;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 登录拦截器
 */
public class LoginHandlerInterceptor implements HandlerInterceptor {
    /**
     * 只需要下面这个(preHandle),配置是否放行配置
     *      ## 返回值boolean
     *      -->true:表示放行
     *      -->false:表示不放行
     *
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {


        /**
         * 1.首先:登录成功之后,应该有用户的session
         *      -->因此如果存在session,说明用户登录了!
         *      -->如果不存在session,说明用户未登录!
         * 2.其次,这个session的值,在LoginController类中设置一个 session参数,
         * 校验用户名密码正确后,给这个session设置一个值,然后执行return。
         *
         */
        Object loginUser = request.getSession().getAttribute("loginUser");
        /**
         * 2. 然后:判断这个Session值"loginUser"是否存在,
         *      -->session存在:说明用户已登录了!
         *      -->session不存在(为空):说明用户未登录!
         */
        if (loginUser == null) {
            //步骤一:session为空,提示"没有权限,请先登录!"。
            request.setAttribute("msg","没有权限,请先登录!");
            //步骤二:并将此信息返回首页"index.html"上显示,重定向回去
            request.getRequestDispatcher("/index.html").forward(request, response);
            //步骤三:未登录,session为空,返回false不放行
            return false;
        }else{
            //登录session不为空,放行-->返回true
            return true;
        }
        /**
         * 此时这个拦截器就写好了。
         *      -->写好后就要配置到bean里面(Spring 的IOC容器中),进行注册!!
         *      -->到MyMvcConfig类中实现此拦截器"LoginHandlerInterceptor"的注册
         */
    }


    /**
     * 下面的拦截之前/之后(postHandle+afterCompletion),不需要写
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

普通的模板,静态资源设置

设置不拦截静态资源也需要先重写addResourceHandlers添加静态资源路径,然后使用excludePathPatterns方法忽略静态资源路径

package com.yu.aaa;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/**").excludePathPatterns("/html/**");
    }
    
   // 添加静态资源访问路径
   @Override
   protected void addResourceHandlers(ResourceHandlerRegistry registry) {
       registry.addResourceHandler("/**")
               .addResourceLocations("classpath:/static/")
               .addResourceLocations("classpath:/templates/");
   }
}

自己总结的一套拦截路径的模板

package com.shaoming.config;

import com.shaoming.interceptors.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;

/**
 * @Auther: shaoming
 * @Date: 2021/1/8 14:11
 * @Description: 注册拦截器配置类
 */
@Configuration//表名这是springboot的配置类
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //定义排除swagger访问的路径配置
        String[] swaggerExcludes=new String[]{"/swagger-ui.html","/swagger-resources/**","/webjars/**"};
        //自定义去除的路径
        String[] myExcludes=new String[]{"/hello","/login"};
        registry.addInterceptor(new LoginInterceptor())
                // addPathPatterns 用于添加拦截规则
                .addPathPatterns("/**")
                //自己定义的不拦截的规则
                .excludePathPatterns(myExcludes)
                //去除拦截springboot的静态文件
                .excludePathPatterns("/html/*")
                .excludePathPatterns("/demo")
                .excludePathPatterns("/")
                .excludePathPatterns("/error")
                //下面是固定格式,如果不配置swagger页面将会访问不了
                .excludePathPatterns(swaggerExcludes);
        WebMvcConfigurer.super.addInterceptors(registry);
    }
    //springboot2.x 静态资源在自定义拦截器之后无法访问的解决方案
//    @Override
//    public void addResourceHandlers(ResourceHandlerRegistry registry) {
//        registry.addResourceHandler("/**") //代表以什么样的请求路径访问静态资源
//                .addResourceLocations("classpath:/static/")
//                .addResourceLocations("classpath:/templates/");
//    }
/**
配置url访问到模板中的页面,省略在controller中写彷佛
*/
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/demo").setViewName("demo");
        registry.addViewController("/").setViewName("demo");
        registry.addViewController("/error").setViewName("error");
    }
}


参考网上案例模板

package com.lzk.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 配置扩展MVC-视图解析器
 *  -->配置接口访问解析跳转
 */
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
        //映射:如果controller返回的请求是"main",就给他返回到dashboard,html这个页面。
        registry.addViewController("/main.html").setViewName("dashboard");

    }

    /**
     *  1. 自定义的国际化放到Spring IOC容器<bean>中,
     *  此时自定义的国际化就生效了!
     *
     *  2. 此方法就是将自己写的组件配置到Spring容器中,@Bean
     *
     */
    @Bean
    public LocaleResolver localeResolver() {
        return new MyLocalResolver();
    }

    /**
     * 1. 下面步骤四:创建一个拦截器相关的类,
     *      -->实现将刚才写好的拦截器"LoginHandlerInterceptor"注册到Spring的IOC容器中,
     *      -->实现拦截器类对象的容器注入bean
     *
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //定义排除swagger访问的路径配置
        String[] swaggerExcludes=new String[]{"/swagger-ui.html","/swagger-resources/**","/webjars/**"};
        //拦截器注入容器,并设置某请求拦截,某些请求不拦截
        registry.addInterceptor(new LoginHandlerInterceptor())
                //-->.addPathPatterns("/**")设置拦截所有请求"/**"
                .addPathPatterns("/**")
                /**
                 * -->排除某一些请求不拦截,
                 *   "index.html":登录页面不拦截,
                 *   "/":首页不拦截
                 *   "user/login":登录请求不拦截
                 *
                 *   "/css/*":静态资源(css,js..):/css下面的静态资源都放行,不拦截
                 */

                .excludePathPatterns("/index.html","/","/user/login","/css/*","/js/**","/img/**")
                .excludePathPatterns(swaggerExcludes);
    }
}

29.springboot打war包模板

1、maven 项目,修改 pom 包

<packaging>jar</packaging>  

改为

<packaging>war</packaging>

2、打包时排除tomcat.

在这里将 scope 属性设置为 provided,这样在最终形成的 WAR 中不会包含这个 JAR 包,因为 Tomcat 或 Jetty 等服务器在运行时将会提供相关的 API 类。

  
         <dependency>
	          <groupId>org.springframework.boot</groupId>
	          <artifactId>spring-boot-starter-tomcat</artifactId>
	          <scope>provided</scope>
        </dependency>

    <!-- 最好加上这个依赖,否者有时候会报错 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>

3、注册启动类

public class ServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }
}

说明:

return builder.sources(SpringbootTestDemoApplication.class);中的SpringbootTestDemoApplication是启动类的名称,根据自己启动类的名称进行修改

30.axios+vue发送异步请求模板

http://rap2api.taobao.org/app/mock/261964/findall这个是阿里在线接口测试工具平台自己设置的接口

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<!-- Bootstrap -->
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
	rel="stylesheet">
<script
	src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<script
	src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
<!-- 引入外部的css文件 -->
<link rel="stylesheet" type="text/css" href="css/emplist.css">

<!-- 引入vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<!-- 引入axios.js -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

</head>
<body>
	 <div id="app">
<!-- 把empList数组里面的数据显示,使用v-for -->
<hr>
<table class="table table-condensed">
<tr v-for="emp in empList">
<td>{{emp.id}}</td>
<td>{{emp.name}}</td>
<td>{{emp.job}} </td>
<td>{{emp.salary}}</td>
</tr>
</table>
<div v-for="emp in empList">
{{emp.id}}  =========> {{emp.name}}  --->{{emp.job}}  ---->{{emp.salary}}
</div>


    </div>
    
    <script>
        /**
         * axios发送ajax请求的步骤
         * 1.引入vue.js和axios.js这两个文件
         * 2.发送ajax请求
         */
        new Vue({
            el:'#app',
            //固定结构
            data:{ //在data定义变量和初始值
                //定义变量,值空数组
             empList:[]
            },
            created(){
                //页面渲染之前执行
                //调用定义的方法
                this.getempList()
            },
            methods:{//编写具体的方法
              //创建方法,查询所有用户数据
              getempList(){
                  //使用axios发送ajax请求
                  //axion.提交方式("请求接口路径").then(箭头函数).catch(箭头函数)
                  axios.get("http://rap2api.taobao.org/app/mock/261964/findall")
                  .then(response=>{
                      //console.log(response);
                      this.empList = response.data
                      console.log(this.empList)
                      
                  })
                  .catch(error=>{
                      console.log("axios发送ajax请求失败");
                  })
              }
            }
        })
    </script>
</body>
</html>

31.springfox 3.0.0的swagger

pom.xml

<!--springfox swagger官方Starter-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>

配置类

package com.shaoming.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

/**
 * Swagger2API文档的配置
 */
@Configuration
public class Swagger2Config {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.shaoming.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("SwaggerUI演示")
                .description("mall-tiny")
                .contact(new Contact("macro", null, null))
                .version("1.0")
                .build();
    }
}

访问地址

http://localhost:8080/swagger-ui/

特别注意

新版本和旧版本文档访问路径发生了变化,新版本为:http://localhost:8088/swagger-ui/ ,旧版本为:http://localhost:8088/swagger-ui.html

32.本地测试跨域配置是否生效

参考网址:

https://blog.csdn.net/qq_41988504/article/details/103599189?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-2.control&dist_request_id=61e22f9f-6c16-4e90-8f32-f2ad92a7f511&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-2.control

随便打开一个网页打开浏览器开发者模式console

var token= "AD3BA267AD984966B3D2179C18FF44F0";
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8080/test');
xhr.setRequestHeader("x-access-token",token);
xhr.send(null);
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}

回车 有数据则说明跨域成功,没有token验证的可以去掉token

正常我们测试期间不需要测试token,所以最终模板是:

var xhr = new XMLHttpRequest();
xhr.open('GET', '测试的url地址');
xhr.send(null);
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}

33.mybatis懒加载

springboot整合mybatis懒加载

mybatis-plus配置

application.properties

#配置mybatis级联查询懒加载
mybatis-plus.configuration.aggressive-lazy-loading=false
mybatis-plus.configuration.lazy-loading-enabled=true
mybaits配置

application.properties

#配置mybatis级联查询懒加载
mybatis.configuration.aggressive-lazy-loading=false
mybatis.configuration.lazy-loading-enabled=true

ssm项目配置懒加载

在conf文件中配置settings:

<settings>
    <!-- 设置驼峰属性 -->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    <!-- 配置懒加载-->
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false"/>
    <!-- 其他配置略 -->
</settings>

34.html常用表单标签使用模板

form.html

<hr><!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Insert title here</title>
	<style> /* 这里可以书写css样式 */
		table{ 
			border:2px solid red;
			/* 设置表格的边框和单元格的边框合并 */
			border-collapse: collapse;
			/* 设置当前元素的左右外边距自适应,即设置
				当前元素水平方向居中 */
			margin-left:auto;
			margin-right:auto;
			/* 设置背景颜色 */
			background: lightgrey;
		}
		td,th{
			border:2px solid red;
			/* 设置单元格的边框和内容之间的距离 */
			padding:5px;
		}
		h1{
			/* 让当前元素的内容居中显示 */
			text-align: center;
			
		}
	</style>
</head>
<body>
	<h1>欢迎注册</h1>
	<form action="#" method="POST">
		<table>
			<tr><!-- 用户名 -->
				<td>用户名:</td>
				<td><!-- 普通文本输入框 -->
					<input type="text"  name="username" 
						placeholder="请输入用户名..."/>
				</td>
			</tr>
			<tr><!-- 密码 -->
				<td>密码:</td>
				<td><!-- 密码输入框 -->
					<input type="password"  name="pwd"/>
				</td>
			</tr>
			<tr><!-- 性别 -->
				<td>性别:</td>		
				<td><!-- 单选框 -->
					<input type="radio"  name="gender"  
						value="male"  checked="checked"/><input type="radio"  name="gender"  
						value="female"/></td>		
			</tr>
			<tr><!-- 爱好 -->
				<td>爱好:</td>		
				<td><!-- 复选框/多选框 -->
					<input type="checkbox"  name="like"  
						value="basketball"  checked="checked"/>篮球
					<input type="checkbox"  name="like"  value="football"/>足球
					<input type="checkbox"  name="like"  value="volleyball"/>排球
				</td>		
			</tr>
			<tr><!-- 城市 -->
				<td>城市:</td>
				<td>
					<select name="city">
						<option value="bj">北京</option>
						<option>上海</option>
						<option selected="selected">广州</option>
						<option>深圳</option>
					</select>
				</td>
			</tr>
			<tr><!-- 自我描述 -->
				<td>自我描述:</td>
				<td>
					<textarea rows="5" cols="30"  name="description"
						placeholder="请输入描述信息..."></textarea>
				</td>
			</tr>
			<tr><!-- 提交按钮 -->
				<td colspan="2"  style="text-align:center;">
					<input type="submit"  value="提交"/>
				</td>
			</tr>
		</table>
	</form>
</body>
</html>


效果如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3MfOmNRf-1655909886918)(https://gitee.com/shao_ming314/picture/raw/master/image/image-20210326215518618.png)]

36.springboot整合mybatis多数据源

参考网址

https://gitee.com/-/ide/project/guanym1994/moredatasource/edit/master/-/src/main/java/com/example/moreDataSource/config/Db2Config.java

https://mybatis.plus/guide/dynamic-datasource.html#%E6%96%87%E6%A1%A3-documentation

说明

springboot整合mybatis多数据源我搜索了网上的解决方案,大概是两种方式,一个是注解+aop动态切换数据源,一个是基于路径选择

基于路径实现多数据源

1.准备数据库表

建表脚本

CREATE TABLE `demo` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(16) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

下面是两个数据库表中的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i2BNDPl0-1655909886919)(https://gitee.com/shao_ming314/picture/raw/master/image/image-20210327142832422.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Tj8L7gP-1655909886920)(https://gitee.com/shao_ming314/picture/raw/master/image/image-20210327142851691.png)]

2.搭建项目

  1. springboot+mybatis脚手架

  2. application.properties配置文件内容如下

server.port=8080
spring.datasource.db1.username=root
spring.datasource.db1.password=root
spring.datasource.db1.jdbc-url=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
spring.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.db2.username=root
spring.datasource.db2.password=root
spring.datasource.db2.jdbc-url=jdbc:mysql://127.0.0.1:3306/yonghedb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
spring.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver

#定义mybatis别名包
mybatis.type-aliases-package=com.shaoming.model.entity
#设置mapper.xml的文件位置
#开启驼峰
mybatis.configuration.map-underscore-to-camel-case=true
#处理返回map有null值得处理
mybatis.configuration.call-setters-on-nulls=true

logging.level.com.shaoming.mapper=debug

  1. 两个数据源配置类
package com.shaoming.config.datasource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**
 * @author shaoming
 * @Date: 2021/3/27 00:56
 * @Description:
 */

@Configuration
@MapperScan(basePackages = {"com.shaoming.mapper.db1"},sqlSessionFactoryRef ="sqlSessionFactoryDb1" )
public class Db1Config {

    @Autowired
    @Qualifier("db1")
    private DataSource dataSourceDb1;

    @Bean
    public SqlSessionFactory sqlSessionFactoryDb1() throws Exception{
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSourceDb1);
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/db1/*.xml"));
        return factoryBean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplateDb1() throws Exception{
        return new SqlSessionTemplate(sqlSessionFactoryDb1());
    }

}
package com.shaoming.config.datasource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**
 * @author shaoming
 * @Date: 2021/3/27 01:52
 * @Description:
 */

@Configuration
@MapperScan(basePackages = {"com.shaoming.mapper.db2"},sqlSessionFactoryRef ="sqlSessionFactoryDb2" )
public class Db2Config {

    @Autowired
    @Qualifier("db2")
    private DataSource dataSourceDb2;

    @Bean
    public SqlSessionFactory sqlSessionFactoryDb2() throws Exception{
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSourceDb2);
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/db2/*.xml"));
        return factoryBean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplateDb2() throws Exception{
        return new SqlSessionTemplate(sqlSessionFactoryDb2());
    }

}

  1. 数据源配置类
package com.shaoming.config.datasource;

/**
 * @author shaoming
 * @Date: 2021/3/27 01:01
 * @Description:
 */

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
 * 由于我们禁掉了自动数据源配置,因些下一步就需要手动将这些数据源创建出来,创建DataSourceConfig类
 *
 */
@Configuration
public class DataSourceConfig {

    @Bean(name = "db1")
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    public DataSource db1(){
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "db2")
    @ConfigurationProperties(prefix = "spring.datasource.db2")
    public DataSource db2(){
        return DataSourceBuilder.create().build();
    }

}

  1. 对应的两个mapper接口

DemoMapper.java

package com.shaoming.mapper.db1;

import com.shaoming.model.entity.Demo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * @Auther: shaoming
 * @Date: 2021/1/11 15:37
 * @Description:
 */
@Mapper
public interface DemoMapper {
    List<Demo> findAll();
}

DemoMapper.xml

<?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.shaoming.mapper.db1.DemoMapper">
    <select id="findAll" resultType="com.shaoming.model.entity.Demo">
        select * from demo
    </select>
</mapper>

Demo2Mapper.java

package com.shaoming.mapper.db2;

import com.shaoming.model.entity.Demo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * @Auther: shaoming
 * @Date: 2021/1/11 15:37
 * @Description:
 */
@Mapper
public interface Demo2Mapper {
    List<Demo> findAll();
}

Demo2Mapper.xml

<?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.shaoming.mapper.db2.Demo2Mapper">
    <select id="findAll" resultType="com.shaoming.model.entity.Demo">
        select * from demo
    </select>
</mapper>

3.项目整体目录

因为是基于目录进行多数据源的配置,所以大概的目录需要分清楚

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IxwYimRF-1655909886920)(https://gitee.com/shao_ming314/picture/raw/master/image/image-20210327143210645.png)]

4.测试

package com.shaoming;

import com.shaoming.mapper.db1.DemoMapper;
import com.shaoming.mapper.db2.Demo2Mapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @author shaoming
 * @Date: 2021/3/27 01:27
 * @Description:
 */
@SpringBootTest
public class DaoTest {
    @Autowired
    private DemoMapper demoMapper;
    @Autowired
    private Demo2Mapper demo2Mapper;
    @Test
    public void testSelectnull(){
        System.out.println(demoMapper.findAll());
        System.out.println(demo2Mapper.findAll());
    }

}

控制台打印:

[Demo(id=1, name=数据源1), Demo(id=2, name=数据源1), Demo(id=3, name=数据源1)]

[Demo(id=1, name=数据源2), Demo(id=2, name=数据源2), Demo(id=3, name=数据源2)]

到此证明mybatis多数据源配置成功

37.springboot整合mybatis-plus多数据源配置

  1. 修改springboot的配置文件

把application.properties改为application.yml

具体内容如下

server:
  port: 8080

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC
          username: root
          password: root
          driver-class-name: com.mysql.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
        slave_1:
          url: jdbc:mysql://localhost:3306/yonghedb?serverTimezone=UTC
          username: root
          password: root
          driver-class-name: com.mysql.jdbc.Driver
        slave_2:
          url: jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
          username: root
          password: root
          driver-class-name: com.mysql.jdbc.Driver

  1. 引入依赖
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.3.2</version>
</dependency>
  1. 写实体类

说明:

方便测试期间,我们就使用一个实体类

Emp.java

package com.shaoming;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
 * @author shaoming
 * @Date: 2021/3/28 15:57
 * @Description:
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@TableName("demo")
public class Demo {
    @TableField("id")
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;
    @TableField("name")
    private String name;
}

3.写对应的3个mapper接口

DemoMasterMapper.java

package com.shaoming;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
 * @author shaoming
 * @Date: 2021/3/28 15:59
 * @Description:
 */
@Mapper
/**
 * 指定是master数据源,当然也可以不指定,默认的就是master数据源
 */
@DS("master")
public interface DemoMasterMapper extends BaseMapper<Demo> {
}

DemoSalve1Mapper.java

package com.shaoming;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
 * @author shaoming
 * @Date: 2021/3/28 15:59
 * @Description:
 */
@Mapper
/**
 * 指定的是slave_1数据源
 */
@DS("slave_1")
public interface DemoSalve1Mapper extends BaseMapper<Demo> {
}

DemoSalve2Mapper.java

package com.shaoming;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
 * @author shaoming
 * @Date: 2021/3/28 15:59
 * @Description:
 */
@Mapper
 /**
 * 指定的是slave_2数据源
 */
@DS("slave_2")
public interface DemoSalve2Mapper extends BaseMapper<Demo> {
}

1.@DS注解的介绍和使用

@DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解

注解结果
没有@DS默认数据源
@DS(“dsName”)dsName可以为组名也可以为具体某个库的名称

2.测试

说明:

使用springboot的测试功能进行测试

package com.shaoming.springbootmpmoredatasource;
import com.shaoming.DemoMasterMapper;
import com.shaoming.DemoSalve1Mapper;
import com.shaoming.DemoSalve2Mapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
 * @author shaoming
 * @Date: 2021/3/28 16:00
 * @Description:
 */
@SpringBootTest
public class DaoTest {
    @Autowired
    private DemoMasterMapper demoMasterMapper;
    @Autowired
    private DemoSalve1Mapper demoSalve1Mapper;
    @Autowired
    private DemoSalve2Mapper demoSalve2Mapper;
    @Test
    public void testfindall() {
        System.out.println("master数据源查出来的信息");
        System.out.println(demoMasterMapper.selectList(null));
        System.out.println("salve_1数据源查出来的信息");
        System.out.println(demoSalve1Mapper.selectList(null));
        System.out.println("salve_2数据源查出来的信息");
        System.out.println(demoSalve2Mapper.selectList(null));
    }
}

控制台打印:

master数据源查出来的信息
[Demo(id=1, name=数据源master), Demo(id=2, name=数据源master), Demo(id=3, name=数据源master)]
salve_1数据源查出来的信息
[Demo(id=1, name=数据源slave_1), Demo(id=2, name=数据源slave_1), Demo(id=3, name=数据源slave_1)]
salve_2数据源查出来的信息
[Demo(id=1, name=数据源slave_2), Demo(id=2, name=数据源slave_2), Demo(id=3, name=数据源slave_2)]

不指定master数据源进行测试

修改DemoMasterMapper.java内容

package com.shaoming;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
 * @author shaoming
 * @Date: 2021/3/28 15:59
 * @Description:
 */
@Mapper
/**
 * 指定是master数据源,当然也可以不指定,默认的就是master数据源
 */
//@DS("master")
public interface DemoMasterMapper extends BaseMapper<Demo> {
}

修改的地方

去掉@DS(“master”)

控制台打印:

master数据源查出来的信息
[Demo(id=1, name=数据源master), Demo(id=2, name=数据源master), Demo(id=3, name=数据源master)]
salve_1数据源查出来的信息
[Demo(id=1, name=数据源slave_1), Demo(id=2, name=数据源slave_1), Demo(id=3, name=数据源slave_1)]
salve_2数据源查出来的信息
[Demo(id=1, name=数据源slave_2), Demo(id=2, name=数据源slave_2), Demo(id=3, name=数据源slave_2)]

结论:

如果使用注解指定数据源,默认的就是master数据源

38.原生ajax模板整理

1.ajax过程

说明:

这个可能是个面试题,问原生ajax的异步请求步骤

(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.

(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.

(3)设置响应HTTP请求状态变化的函数.

(4)发送HTTP请求.

(5)获取异步调用返回的数据.

(6)使用JavaScript和DOM实现局部刷新.

2.准备测试的接口

使用的是RAP接口在线测试工具

RAP官网网址:http://rap2.taobao.org/

测试的接口信息

get请求

url:http://rap2api.taobao.org/app/mock/261964/findall

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cDnQ8umY-1655909886920)(https://gitee.com/shao_ming314/picture/raw/master/image/image-20210328210957951.png)]

3.ajax测试模板

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style> /* 这里可以书写css样式 */
		table{ 
			border:2px solid red;
			/* 设置表格的边框和单元格的边框合并 */
			border-collapse: collapse;
			/* 设置当前元素的左右外边距自适应,即设置
				当前元素水平方向居中 */
			margin-left:auto;
			margin-right:auto;
			/* 设置背景颜色 */
			background: lightgrey;
		}
		td,th{
			border:2px solid red;
			/* 设置单元格的边框和内容之间的距离 */
			padding:5px;
		}
		h1{
			/* 让当前元素的内容居中显示 */
			text-align: center;
			
		}
	</style>
</head>
<body>
	<h1>Goods Ajax Pages</h1>
	<div style="text-align: center;color: #000;">
		<button id="btn1">点击发送原生的ajax</button>
	</div>
    <table>
       <thead>
          <tr>
            <th>id</th>
            <th>name</th>
            <th>job</th>
            <th>salary</th>
          </tr>
       </thead>
       <tbody id="tbodyId">
         <tr><td colspan="4">Data loading ...</td></tr>
       </tbody>
    </table>
	<script type="text/javascript">
	var btn = document.getElementById("btn1");
	btn.onclick=function(){
		alert("单击事件是否绑定成功!!!");
		ajaxGet();
	}
     function ajaxGet(){
      //页面加载完成向服务端再次发起请求,获取服务端数据,然后更新页面
      //1.构建XHR对象并注册监听
      var xhr=new XMLHttpRequest();
      //注册监听函数(监听与服务端通讯过程)
      xhr.onreadystatechange=function(){//callback
    	  //readyState==4表示通讯结束
    	  //status==200 表示服务端响应OK
    	  if(xhr.readyState==4&&xhr.status==200){
    		  //responseText表示服务端响应的结果
    		  //console.log(xhr.responseText);//json格式字符串
    		  //将服务端响应的json格式字符串,转换为json格式的JS对象
    		  var result=JSON.parse(xhr.responseText);
    		  doHandleResponseResult(result);
    	  }
      }
      //2.建立连接
      var url="http://rap2api.taobao.org/app/mock/261964/findall"
      xhr.open("GET",url,true);//true代表异步
      //3.发送请求
      xhr.send(null);//get请求send方法内部不传参数
      }
      //处理响应结果
      function doHandleResponseResult(result){
    	  console.log(result);
    	  //1.获得tbody对象,清空原有内容
    	  var tBody=document.getElementById("tbodyId");
    	  tBody.innerHTML="";
    	  //2.迭代result记录,并将记录呈现在tbody位置
    	  for(var i=0;i<result.length;i++){
    		  //2.1构建tr对象
    		  var tr=document.createElement("tr");
    		  //2.2构建td对象,并追加到tr中
    		  var td=document.createElement("td");
    		  td.innerText=result[i].id;
    		  tr.appendChild(td);
    		  
    		  td=document.createElement("td");
    		  td.innerText=result[i].name;
    		  tr.appendChild(td);
    		  
    		  td=document.createElement("td");
    		  td.innerText=result[i].job;
    		  tr.appendChild(td);
    		  
    		  td=document.createElement("td");
    		  td.innerText=result[i].salary;
    		  tr.appendChild(td);
    		  
    		  //2.3将tr对象追加到tbody中
    		  tBody.appendChild(tr);
    	  }
      }
    //   ajaxGet();
    </script>
</body>
</html>

4.测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aST8bDuY-1655909886920)(https://gitee.com/shao_ming314/picture/raw/master/image/image-20210328211129503.png)]

发送ajax请求的页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EW1qtASN-1655909886921)(https://gitee.com/shao_ming314/picture/raw/master/image/image-20210328211150656.png)]

39.springboot整合swagger+knife4j

准备工作

准备一个springboot的单体应用作为测试

1.整合swagger3.0

1.1引入依赖

<!--springfox swagger官方Starter-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>

1.2添加配置类

package com.atguigu.yygh.hosp.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

/**
 * Swagger2API文档的配置
 * 访问地址
 * http://localhost:端口号/swagger-ui/
 * 我搭建项目喜欢使用springboot默认端口8080
 * http://localhost:8080/swagger-ui/
 *http://项目的ip地址:项目端口号/swagger-ui/
 */
@Configuration
public class Swagger2Config {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                /**
                 * 重点说明:
                 * 其余都是可以默认,但是controller扫描的路径一定要该队,是该项目的controller包路径
                 */
                .apis(RequestHandlerSelectors.basePackage("com.atguigu.yygh.hosp.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                /**
                 * 指定项目的名称和主题
                 */
                .title("xxxx演示")
                /**
                 * 描述项目的用途
                 */
                .description("xxxxxdescription")
                /**
                 * name:使用者的姓名
                 * url:使用者的相关技术文章
                 * email:使用者的邮箱地址
                 */
                .contact(new Contact("xxx", "xxxxx", "xxxxx"))
                .version("1.0")
                .build();
    }
}

2.整合knife4j

说明:整合knif4j特别简单,引入一个依赖即可

引入依赖

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.2</version>
        </dependency>

使用

1.访问网址

swagger3的访问网址

http://项目的ip地址:项目端口号/swagger-ui/

示例

localhost:8080/swagger-ui

knife4j访问网址

http://项目的ip地址:项目端口号/doc.html

示例

localhost:8080/doc.html

40.springboot整合mybatis-plus逆向工程配置

简介

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

添加的依赖

   <!-- springboot整合mybatis-plus逆向工程 -->
        <!-- mybatis-plus逆向工程依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.2.0</version>
        </dependency>
        <!-- MyBatis-Plus 支持 Velocity(默认) -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>

代码模板

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.ArrayList;

/**
 * @author shaoming
 * @Date: 2021/4/8 12:00
 * @Description:
 */
// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {

    public static void main(String[] args) {
        // 需要构建一个 代码自动生成器 对象
        AutoGenerator mpg = new AutoGenerator();
        // 配置策略
        // 1、全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath+"/src/main/java");
        gc.setAuthor("kwhua");//作者名称
        gc.setOpen(false);
        gc.setFileOverride(false); // 是否覆盖
        gc.setIdType(IdType.AUTO);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setSwagger2(true);//实体属性 Swagger2 注解

        // 自定义文件命名,注意 %s 会自动填充表实体属性!
        gc.setServiceName("%sService");
        gc.setControllerName("%sController");
        gc.setServiceName("%sService");
        gc.setServiceImplName("%sServiceImpl");
        gc.setMapperName("%sMapper");
        gc.setXmlName("%sMapper");

        mpg.setGlobalConfig(gc);

        //2、设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/yygh_hosp?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
         dsc.setDriverName("com.mysql.cj.jdbc.Driver"); //mysql5.6以下的驱动
        dsc.setUsername("root");
        dsc.setPassword("root");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);
        //3、包的配置
        PackageConfig pc = new PackageConfig();
        pc.setParent("com.atguigu.yygh.hosp.utils"); //包名
        pc.setModuleName("codegenerator"); //模块名
        pc.setEntity("entity");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setController("controller");
        mpg.setPackageInfo(pc);

        //4、策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("user"); // 设置要映射的表名
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true); // 自动lombok;
        strategy.setLogicDeleteFieldName("deleted");
        // 自动填充配置
        TableFill gmtCreate = new TableFill("create_time", FieldFill.INSERT);
        TableFill gmtModified = new TableFill("update_time",FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(gmtCreate);
        tableFills.add(gmtModified);
        strategy.setTableFillList(tableFills);
        // 乐观锁
        strategy.setVersionFieldName("version");
        //根据你的表名来建对应的类名,如果你的表名没有下划线,比如test,那么你就可以取消这一步
        strategy.setTablePrefix("t_");
        strategy.setRestControllerStyle(true); //rest请求
        //自动转下划线,比如localhost:8080/hello_id_2
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setSuperEntityClass("BaseEntity");
        mpg.setStrategy(strategy);
        mpg.execute(); //执行
    }

}

需要注意的配置项

1.是否添加swagger注解配置项

现在一般项目都是整合了swagger接口工具,所以我们一般需要添加swagger注解,添加此注解无侵害性

 gc.setSwagger2(true);//实体属性 Swagger2 注解

2.配置数据库连接信息

dsc.setUrl("jdbc:mysql://localhost:3306/yygh_hosp?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
                dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        // dsc.setDriverName("com.mysql.jdbc.Driver"); //mysql5.6以下的驱动
        dsc.setUsername("root");
        dsc.setPassword("root");

说明:

jdbc连接信息使用

useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8

防止出现时区差异或者中文乱码

3.指定主键自增的类型

gc.setIdType(IdType.AUTO);

4.指定模板引擎

说明:

添加 模板引擎 依赖,MyBatis-Plus 支持 Velocity(默认)、Freemarker、Beetl,用户可以选择自己熟悉的模板引擎,如果都不满足您的要求,可以采用自定义模板引擎

我们就是用mybatis-plus的默认引擎,在项目中添加如下依赖

        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>

5.设置自动填充和乐观锁

说明:

自动填充,乐观锁的列明要和实体类的属性名一致

      //自动填充       
       TableFill gmtCreate = new TableFill("create_time", FieldFill.INSERT);
        TableFill gmtModified = new TableFill("update_time",FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(gmtCreate);
        tableFills.add(gmtModified);
        strategy.setTableFillList(tableFills);
        // 乐观锁
        strategy.setVersionFieldName("version");

5.设置需要生成的表名

说明:

需要生成的表名和数据库一致,可以同事生成多个表的逆向文件

 strategy.setInclude("user"); // 设置要映射的表名

6.设置包名和模块名

具体根据情况而定

  pc.setParent("com.mybatis-plus"); //包名
  pc.setModuleName("genertor"); //模块名

7.设置实体类继承的实体类

strategy.setSuperEntityClass("BaseEntity");

踩坑记录

报错信息

ClassNotFoundException: com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator

原因

mybatis-plus-generator包和mybatis-plus-boot-starter包版本不对应

41.springmvc四种类型返回值

对应测试的controller

TestController

import com.example.demo.demos.model.Book;
import com.example.demo.demos.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author shaoming
 * @Date: 2021/4/9 17:18
 * @Description:
 */
@Controller
public class TestController {
    @RequestMapping("book")//get请求
    // @ResponseBody
    /**
     * 返回值为ModelAndView
     */
    public ModelAndView getAllBook() {
        ModelAndView mv = new ModelAndView();
        List<Book> books = new ArrayList<Book>();
        Book b1 = new Book();
        b1.setId(1).setAuthor("罗贯中").setName("三国演义");
        Book b2 = new Book();
        b2.setId(2).setAuthor("曹雪芹").setName("红楼梦");
        books.add(b1);
        books.add(b2);
        mv.addObject("bs", books);
        mv.setViewName("book");
        return mv;
    }

    /**
     * 返回值为void类型
     */
    @RequestMapping("/test2")//get请求
    @ResponseBody
    public void test2() {
        //你的代码
        System.out.println("controller方法时没有返回值");
    }

    /**
     * 返沪void类型的重定向,通过status和header进行设置(不常用)
     * @param resp
     * @throws IOException
     */
    @RequestMapping("/test1")//get请求
    @ResponseBody
    public void test1(HttpServletResponse resp) {
        resp.setStatus(302);
        resp.addHeader("Location", "/book");
    }

    /**
     * 返沪void类型的重定向
     * @param resp
     * @throws IOException
     */
    @RequestMapping("/test11")//get请求
    @ResponseBody
    public void test11(HttpServletResponse resp) throws IOException {
        resp.sendRedirect("/book");
    }

    @RequestMapping("/test5")//get请求
    @ResponseBody
    public void test5(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        req.getRequestDispatcher("/book").forward(req, resp);
    }

    /**
     * 返回值为void,并页面输出json格式字符窜
     * @param resp
     * @throws IOException
     */
    @RequestMapping("/test3")//get请求
    @ResponseBody
    public void test3(HttpServletResponse resp) throws IOException {
        /**
         * 设置响应的数据为json格式
         */
        resp.setContentType("application/json;charset=utf8");
        PrintWriter out = resp.getWriter();
        List<Book> books = new ArrayList<Book>();
        Book b1 = new Book();
        b1.setId(1).setAuthor("罗贯中").setName("三国演义");
        Book b2 = new Book();
        b2.setId(2).setAuthor("曹雪芹").setName("红楼梦");
        books.add(b1);
        books.add(b2);
        /**
         * 通过jackson工具类把java对象转为json格式的字符窜
         */
        String booksJson = new ObjectMapper().writeValueAsString(books);
        out.write(booksJson);
        out.flush();
        out.close();
    }

    /**
     * 返回视图名称并通过model获取数据
     * @param model
     * @return
     */
    @RequestMapping("/test4")
    public String test4(Model model) {
        Book b1 = new Book();
        b1.setId(1).setAuthor("罗贯中").setName("三国演义");
        model.addAttribute("book", b1);
        model.addAttribute("username", "张三");
        return "bookinfo";
    }

    /**
     * 返回string类型的重定向
     * @return
     */
    @RequestMapping("/test6")
    public String test6() {
        return "redirect:/book";
    }

    /**
     * 返回string类型的转发
     * @return
     */
    @RequestMapping("/test7")
    public String test7() {
        return "forward:/book";
    }

    /**
     * 返回json
     * @return
     */
    @GetMapping("/user")//get请求
    @ResponseBody
    public User getUser() {
        User user = new User();
        List<String> favorites = new ArrayList<>();
        favorites.add("足球");
        favorites.add("篮球");
        user.setFavorites(favorites).setUsername("张三").setPassword("123456");
        return user;
    }

    @GetMapping("/users")//get请求
    @ResponseBody
    public List<User> getUsers() {
        List<User> users = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setPassword("张三" + i).setPassword("pwd" + i)
                    .setFavorites(new ArrayList<String>(Arrays.asList("football", "basketball")));
            users.add(user);
        }
        return users;
    }
}

测试的模板引擎页面(使用的是thymeleaf模板引擎)

book.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap 101 Template</title>
    <!-- Bootstrap -->
    <link
            href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
            rel="stylesheet">
    <script
            src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
    <script
            src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
    <style type="text/css">
        #div2{
            text-align: center;
            border: 3px solid red;
        }
        a{
            font-size: 25px;
        }
    </style>
</head>
<body>
<!-- 查询所有员工列表页面 -->
<h1 align="center">book列表信息</h1>
<!-- 这个表格示显示员工数据的 -->
<div id="div2">
    <table class="table table-condensed">
        <thead>
        <tr>
            <td>编号</td>
            <td>ID</td>
            <td>NAME</td>
            <td>JOB</td>
        </thead>
        <tbody>
        <tr th:each="book,varstatus:${bs}">
            <td th:text="${varstatus.count}"></td>
            <td th:text="${book.id}"></td>
            <td th:text="${book.name}"></td>
            <td th:text="${book.author}"></td>
        </tr>
        </tbody>
    </table>
</div>
</body>
</html>

bookinfo.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head> 
    <title>Getting Started: Serving Web Content</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <p th:text="'页面获取model的username的值为: , ' + ${username} + '!'" />
    <hr>
    <hr>
    <p th:text="'页面获取model的book的信息book的id为:  , ' + ${book.id}" />
    <p th:text="'页面获取model的book的信息book的author为:  , ' + ${book.author}" />
    <p th:text="'页面获取model的book的信息book的name为:  , ' + ${book.name}  " />
</body>
</html>

42.springcache+redis 缓存数据

  1. 引入依赖
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- spring2.X集成redis所需common-pool2-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.0</version>
</dependency>

  1. 编写redis配置类
@Configuration
@EnableCaching
public class RedisConfig {

/**
     * 自定义key规则
     * @return
*/
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
for (Object obj : params) {
                    sb.append(obj.toString());
                }
return sb.toString();
            }
        };
    }

/**
     * 设置RedisTemplate规则
     * @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

//序列号key value
redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.afterPropertiesSet();
return redisTemplate;
    }

/**
     * 设置CacheManager缓存规则
     * @param factory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();

        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
return cacheManager;
    }
}

  1. 标签解释

@Cacheable

根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。

@CachePut

使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。一般用在新增方法上。

@CacheEvic

使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上

  1. 示例代码
/**
 * 根据上级id获取子节点数据列表
 * @param parentId
*/
@Cacheable(value = "dict",keyGenerator = "keyGenerator")
@Override
public List<Dict> findByParentId(Long parentId) {
       List<Dict> dictList = dictMapper.selectList(new QueryWrapper<Dict>().eq("parent_id", parentId));
       dictList.stream().forEach(dict -> {
boolean isHasChildren = this.isHasChildren(dict.getId());
           dict.setHasChildren(isHasChildren);
       });
return dictList;
}
/**
 * 导入
 * allEntries = true: 方法调用后清空所有缓存
 * @param file
*/
@CacheEvict(value = "dict", allEntries=true)
@Override
public void importData(MultipartFile file) {
   ExcelHelper fileHelper = new ExcelHelper(DictEeVo.class);
   List<DictEeVo> dictVoList = fileHelper.importExcel(file);
if(!CollectionUtils.isEmpty(dictVoList)) {
dictMapper.insertBatch(dictVoList);
   }
}

43.StringUtils和StrUtil(Hutool)常用操作字符窜方法使用模板

整理原因

springboot的StringUtils几个方法怎么判空总是分不清楚,整理好了就可以很好的使用

import cn.hutool.core.util.StrUtil;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.StringUtils;

/**
 * @author shaoming
 * @Date: 2021/4/25 09:21
 * @Description:
 */
public class StringUtilsTest {
    /**
     * @author shaoming
     * @Date: 2021/4/23 16:47
     * @Description:
     */
    @SpringBootTest
    public static class StringUitilTest {
        @Test
        public void testCreateString() {
            String str1 = "";
            String str2 = "   ";
            String str3 = null;
            String str4 = " 我是string的内容 ";
        }

        /**
         * 测试org.springframework.util.StringUtils工具判断字符窜是否为空的api
         */
        @Test
        public void testStringNotEmptyBySpringUtils() {
            String str1 = "";
            String str2 = "   ";
            String str3 = null;
            String str4 = " 我是string的内容 ";
            boolean empty1 = StringUtils.isEmpty(str1);
            boolean empty2 = StringUtils.isEmpty(str2);
            boolean empty3 = StringUtils.isEmpty(str3);
            boolean empty4 = StringUtils.isEmpty(str4);
            System.out.println(empty1);
            System.out.println(empty2);
            System.out.println(empty3);
            System.out.println(empty4);
            /*
            控制台打印:
            true
            false
            true
            false
             */
        }

        /**
         * org.apache.commons.lang3.StringUtils这个工具类进行字符窜判空的工具类
         * 说明:
         * 使用这个工具类需要引入以下依赖
         * <dependency>
         * <groupId>org.apache.commons</groupId>
         * <artifactId>commons-lang3</artifactId>
         * <version>3.1</version>
         * </dependency>
         */
        @Test
        public void testStirngNotEmptyByapacheCommonsLangsStringUtils() {
            String str1 = "";
            String str2 = "   ";
            String str3 = null;
            String str4 = " 我是string的内容 ";
            System.out.println("测试isBlank方法");
            System.out.println(org.apache.commons.lang3.StringUtils.isBlank(str1));
            System.out.println(org.apache.commons.lang3.StringUtils.isBlank(str2));
            System.out.println(org.apache.commons.lang3.StringUtils.isBlank(str3));
            System.out.println(org.apache.commons.lang3.StringUtils.isBlank(str4));
            System.out.println("测试isEmpty方法");
            System.out.println(org.apache.commons.lang3.StringUtils.isEmpty(str1));
            System.out.println(org.apache.commons.lang3.StringUtils.isEmpty(str2));
            System.out.println(org.apache.commons.lang3.StringUtils.isEmpty(str3));
            System.out.println(org.apache.commons.lang3.StringUtils.isEmpty(str4));
            /*
             * 控制台打印
             * 测试isBlank方法
             * true
             * true
             * true
             * false
             * 测试isEmpty方法
             * true
             * false
             * true
             * false
             */
        }

        /**
         * 测试hutool的String判空工具类
         * 说明:
         * 使用StrUtil需要在mavne项目中引入hutool的依赖
         * <dependency>
         * <groupId>cn.hutool</groupId>
         * <artifactId>hutool-all</artifactId>
         * <version>5.6.3</version>
         * </dependency>
         */
        @Test
        public void testStringByHutoolofStrUtil() {
            String str1 = "";
            String str2 = "   ";
            String str3 = null;
            String str4 = " 我是string的内容 ";
            System.out.println("测试hutool中String判空的isBlank方法");
            System.out.println(StrUtil.isBlank(str1));
            System.out.println(StrUtil.isBlank(str2));
            System.out.println(StrUtil.isBlank(str3));
            System.out.println(StrUtil.isBlank(str4));
            System.out.println("测试hutool中String判空的isEmpty方法");
            System.out.println(StrUtil.isEmpty(str1));
            System.out.println(StrUtil.isEmpty(str2));
            System.out.println(StrUtil.isEmpty(str3));
            System.out.println(StrUtil.isEmpty(str4));
            /*
             * 控制台打印
             * 测试hutool中String判空的isBlank方法
             * true
             * true
             * true
             * false
             * 测试hutool中String判空的isEmpty方法
             * true
             * false
             * true
             * false
             */
        }

    }
}

44.测试跨域的html页面

cros.html

<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body>
<h2>Hello World!</h2>
<script type="text/javascript">
    function fun1(){
        var request = new XMLHttpRequest();
        request.open("GET","http://www.shaoming.club:80/app/center/getsysconfigbygroup")
        request.send();
        request.onreadystatechange = function(){
            if(request.status==200 && request.readyState == 4){
                console.log("响应的结果" + request.responseText)
            }
        }
    }
</script>
</body>
    <input type="button" value="跨域调用" onclick="fun1()">
</html>

说明:

使用原生ajax发送请求,只要满足跨域条件我们发送ajax请求就成功返回json数据

如果成功,证明后端接口做了跨域处理

45.springboot整合knife4j(快速通用版)

引入pom.依赖

<!-- springboot整合knife4j依赖(低版本也可以用1.5.xx版本以后都是可用) -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.4</version>
        </dependency>

swagger配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;


@Configuration
@EnableSwagger2
public class SwaggerConfiguration {


    @Bean(value = "defaultApi2")
    public Docket defaultApi2() {
        Docket docket=new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName("低版本版本")
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.jsbs.ordergood.controller"))
                //.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("swagger-bootstrap-ui-demo RESTful APIs")
                .description("# swagger-bootstrap-ui-demo RESTful APIs")
                .termsOfServiceUrl("http://www.xx.com/")
                .contact("xx@qq.com")
                .version("1.0")
                .build();
    }

}

knife4j访问网址

http://项目的ip地址:项目端口号/doc.html

说明:

apis(RequestHandlerSelectors.basePackage("com.xiaominfo.knife4j.demo.web"))指定对应controller包路劲即可

46.maven配置阿里云镜像的两种方式

配置方式

第一种方式(settings.xml文件)

在mirrors节点下加入一个新的mirror节点,配置阿里镜像地址,完整配置如下:

<mirrors>
 	 <mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>        
    </mirror>
  </mirrors>
第二种方式(pom.xml方式)

修改项目pom.xml,在repositories节点下加入repository节点,配置阿里镜像地址,完整配置如下:

此配置参考renren-genertor项目的pom.xml配置,项目网址:https://gitee.com/renrenio/renren-generator

<repositories>
		<repository>
			<id>public</id>
			<name>aliyun nexus</name>
			<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
			<releases>
				<enabled>true</enabled>
			</releases>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>public</id>
			<name>aliyun nexus</name>
			<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>

区别

第一种方式是全局的方式配置

第二种方式只能当前项目生效

47.Vagrantfile模板

说明:

vagrant 安装 centos7 的模板

# -*- mode: ruby -*-
# vi: set ft=ruby :

# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
  # The most common configuration options are documented and commented below.
  # For a complete reference, please see the online documentation at
  # https://docs.vagrantup.com.

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://vagrantcloud.com/search.
  config.vm.box = "centos/7"

  # Disable automatic box update checking. If you disable this, then
  # boxes will only be checked for updates when the user runs
  # `vagrant box outdated`. This is not recommended.
  # config.vm.box_check_update = false

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # NOTE: This will enable public access to the opened port
  # config.vm.network "forwarded_port", guest: 80, host: 8080

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine and only allow access
  # via 127.0.0.1 to disable public access
  # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"

  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  config.vm.network "private_network", ip: "192.168.56.10"

  # Create a public network, which generally matched to bridged network.
  # Bridged networks make the machine appear as another physical device on
  # your network.
  # config.vm.network "public_network"

  # Share an additional folder to the guest VM. The first argument is
  # the path on the host to the actual folder. The second argument is
  # the path on the guest to mount the folder. And the optional third
  # argument is a set of non-required options.
  # config.vm.synced_folder "../data", "/vagrant_data"

  # Provider-specific configuration so you can fine-tune various
  # backing providers for Vagrant. These expose provider-specific options.
  # Example for VirtualBox:
  #
  # config.vm.provider "virtualbox" do |vb|
  #   # Display the VirtualBox GUI when booting the machine
  #   vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
  #   vb.memory = "1024"
  # end
  #
  # View the documentation for the provider you are using for more
  # information on available options.

  # Enable provisioning with a shell script. Additional provisioners such as
  # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
  # documentation for more information about their specific syntax and use.
  # config.vm.provision "shell", inline: <<-SHELL
  #   apt-get update
  #   apt-get install -y apache2
  # SHELL
  # 设置 虚拟机的内存和cpu核数
  config.vm.provider "virtualbox" do |v|
  v.memory = 2048
  v.cpus = 2
  end
end

48.springboot使用undertow代替tomcat

参考网址:

若依文档使用使用undertow来替代tomcat容器

http://doc.ruoyi.vip/ruoyi/document/cjjc.html#%E9%9B%86%E6%88%90atomikos%E5%AE%9E%E7%8E%B0%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1

两者对比

https://mp.weixin.qq.com/s/PHaGWVEP7RSx5GBOsH4Yew

SpingBoot中我们既可以使用Tomcat作为Http服务,也可以用Undertow来代替。Undertow在高并发业务场景中,性能优于Tomcat。所以,如果我们的系统是高并发请求,不妨使用一下Undertow,你会发现你的系统性能会得到很大的提升。

1、ruoyi-framework\pom.xml模块修改web容器依赖,使用undertow来替代tomcat容器

 <!-- SpringBoot Web容器 -->
 <dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
	 <exclusions>
		 <exclusion>
			 <artifactId>spring-boot-starter-tomcat</artifactId>
			 <groupId>org.springframework.boot</groupId>
		 </exclusion>
	 </exclusions>
</dependency>

<!-- web 容器使用 undertow -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

2、修改application.yml,使用undertow来替代tomcat容器

# 开发环境配置
server:
  # 服务器的HTTP端口,默认为80
  port: 80
  servlet:
    # 应用的访问路径
    context-path: /
  # undertow 配置
  undertow:
    # HTTP post内容的最大大小。当值为-1时,默认值为大小是无限的
    max-http-post-size: -1
    # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
    # 每块buffer的空间大小,越小的空间被利用越充分
    buffer-size: 512
    # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
    io-threads: 8
    # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
    worker-threads: 256
    # 是否分配的直接内存
    direct-buffers: true

nginx 配置 http

参考网址:

https://cloud.tencent.com/document/product/400/35244

参数说明:

cloud.tencent.com_bundle.crt 证书文件
cloud.tencent.com_bundle.pem 证书文件(可忽略该文件)
cloud.tencent.com.key 私钥文件
cloud.tencent.com.csr CSR 文件

基础模板

server {
        #SSL 访问端口号为 443
        listen 443 ssl; 
        #填写绑定证书的域名
        server_name cloud.tencent.com; 
        #证书文件名称
        ssl_certificate cloud.tencent.com_bundle.crt; 
        #私钥文件名称
        ssl_certificate_key cloud.tencent.com.key; 
        ssl_session_timeout 5m;
        #请按照以下协议配置
        ssl_protocols TLSv1.2 TLSv1.3; 
        #请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
        ssl_prefer_server_ciphers on;
        location / {
           #网站主页路径。此路径仅供参考,具体请您按照实际目录操作。
           #例如,您的网站运行目录在/etc/www下,则填写/etc/www。
            root html; 
            index  index.html index.htm;
        }
    }

http 重定向到 https 模板

server {
        #SSL 访问端口号为 443
        listen 443 ssl; 
        #填写绑定证书的域名
        server_name cloud.tencent.com; 
        #证书文件名称
        ssl_certificate cloud.tencent.com_bundle.crt; 
        #私钥文件名称
        ssl_certificate_key cloud.tencent.com.key; 
        ssl_session_timeout 5m;
        #请按照以下协议配置
        ssl_protocols TLSv1.2 TLSv1.3; 
        #请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
        ssl_prefer_server_ciphers on;
        location / {
           #网站主页路径。此路径仅供参考,具体请您按照实际目录操作。
           #例如,您的网站运行目录在/etc/www下,则填写/etc/www。
            root html; 
            index  index.html index.htm;
        }
    }

halo 博客 和 docsify 的 https 配置模板

halo博客使用 https

docsify 知识库文档使用 http

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
	worker_connections  1024;
}


http {
	include       mime.types;
	default_type  application/octet-stream;



	sendfile        on;

	keepalive_timeout  65;

#gzip  on;

# another virtual host using mix of IP-, name-, and port-based configuration
#


# HTTPS server
upstream halo {
        server 127.0.0.1:8090;
	}

        server {
                listen 8080;
                location / {
                        root /opt/docsify/;
                        index index.html index.html;
                }

        }



 server {
        #SSL 访问端口号为 443
        listen 443 ssl; 
        #填写绑定证书的域名
        server_name cloud.tencent.com; 
        #证书文件名称
        ssl_certificate www.shaoming.club.crt; 
        #私钥文件名称
        ssl_certificate_key www.shaoming.club.key; 
        ssl_session_timeout 5m;
        #请按照以下协议配置
        ssl_protocols TLSv1.2 TLSv1.3; 
        #请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
        ssl_prefer_server_ciphers on;
        location / {
                        gzip_static on; # 静态压缩
                        add_header Cache-Control public,max-age=60,s-maxage=60; # 配置缓存
                        proxy_pass http://127.0.0.1:8090;
                        proxy_set_header HOST $host;
                        proxy_set_header X-Forwarded-Proto $scheme;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
 server {
    listen 80;
    server_name localhost;
    #将请求转成https
    #rewrite ^(.*)$ https://$host$1 permanent; # 另一种方式 ,不建议使用 , 下面使用是腾讯云方案
    return 301 https://$host$request_uri;
}
}

halo 博客 和 docsify 的 http 配置模板


#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
	worker_connections  1024;
}


http {
	include       mime.types;
	default_type  application/octet-stream;



	sendfile        on;

	keepalive_timeout  65;

#gzip  on;
	upstream halo {
		server 127.0.0.1:8090;
	}

	server {
		listen 80;
		listen [::]:80;
		server_name www.shaoming.club;
		client_max_body_size 1024m;
		location / {
      gzip_static on; # 静态压缩
      add_header Cache-Control public,max-age=60,s-maxage=60; # 配置缓存  
			proxy_pass http://halo;
			proxy_set_header HOST $host;
			proxy_set_header X-Forwarded-Proto $scheme;
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		}

	}
	server {
		listen 8080;
		location / {
			root /opt/docsify/;
			index index.html index.html;
		}

	}


# another virtual host using mix of IP-, name-, and port-based configuration
#


# HTTPS server
#
#server {
#    listen       443 ssl;
#    server_name  localhost;

#    ssl_certificate      cert.pem;
#    ssl_certificate_key  cert.key;

#    ssl_session_cache    shared:SSL:1m;
#    ssl_session_timeout  5m;

#    ssl_ciphers  HIGH:!aNULL:!MD5;
#    ssl_prefer_server_ciphers  on;

#    location / {
#        root   html;
#        index  index.html index.htm;
#    }
#}

}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值