目錄
?
一、相關概念
1.spring框架
2.springcloud
3.SpringBoot項目
4.注解
5.SpringBoot的文件結構
6.啟動類原理
二、相關操作
1.Jar方式打包
2.自定義返回的業務狀態碼
?3.Jackson
4.加載配置文件
5.異常處理
三、優化配置
?1.簡化sql語句
2.查詢操作
復雜查詢
?一對一聯表查詢
一對多聯表查詢
小結
?
一、相關概念
1.spring框架
也可稱為DI,IoC,AOP框架,相當于是一個容器,每一個對象就是一個bean
對于項目構建過程:Controller -> Service -> Dao
未用框架時,需要實例化service實現類來調用方法
private UserService userService = new UserService();
使用Spring框架后,可通過注解來實現自動裝配對象
@Autowire
private UserService userService
2.springcloud
是基于springboot, 只不過是在之前基礎上多了幾個插件包
3.SpringBoot項目
SpringBoot是一個通過注解簡化配置的web開發框架。
有兩種創建方式:
本地創建-先創建一個普通maven項目,再參考官方文檔:Getting Started | Building an Application with Spring Boot
添加相關maven依賴;
在線創建 -https://start.spring.io/
開發JSON接口,可通過@RestController注解實現,可將要顯示的數據序列化成JSON對象.
4.注解
本質是繼承Annotation接口,起到說明、配置的作用
常見注解:
@Controller用于標記類是一個控制器,返回頁面的時使用,但如果要返回JSON,需要再添加@ResponseBody
@RestController 用于標記類是一個控制器,并返回JSON數據,實現接口返回數據會被序列化為JSON,相當于@Controller+@ResponseBody
@RequestMapping 設置路由映射,為某個方法設置子路徑
@GetMapping用于設置get請求查詢接口的路徑,相當于@RequestMapping(method = RequestMethod.GET)
同理有
@PostMapping = @RequestMapping(method = RequestMethod.POST) @PutMapping = @RequestMapping(method = RequestMethod.PUT)
@DeleteMapping = @RequestMapping(method = RequestMethod.DELETE)
@SpringBootApplication 用于標記是SringBoot應用,里面包含多個子注解,相當于@Configuration(spring掃描注入)+@EnableAutoConfiguration(自動載入所需Bean)+@ComponentScan(spring掃描包的范圍)
@Component標記這個是一個組件,相當于在啟動類中添加@Bean,new一個對象
@Scheduled注解是一個定時任務注解,可以在方法上添加,表示這個方法是一個定時任務方法
5.SpringBoot的文件結構
- src/main/java:存放代碼
- src/main/resources:存放靜態資源
- static: 存放靜態文件,比如 css、js、image, (訪問方式?http://localhost:8080/js/main.js)
- templates:存放靜態頁面jsp,html,tpl
- config:存放配置文件,application.properties
靜態文件加載順序
META/resources ----->resources -------->static ------->public
6.啟動類原理
啟動類和controller分開存放,啟動類要放在根目錄下,在啟動類上只需要注解@SpringBootApplication
二、相關操作
1.Jar方式打包
只需在pom.xml文件中添加插件
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>?
如果沒有加,則執行jar包 ,報錯如下 java -jar spring-boot-demo-0.0.1-SNAPSHOT.jar no main manifest attribute, in spring-boot-demo-0.0.1-SNAPSHOT.jar
打包與啟動命令
- 構建:mvn install
target目錄下的jar包就是打包后項目
- 進到對應的target
- 目錄啟動 java -jar xxxxx.jar
- 保持后臺運行,守護進程 nohup java -jar xxx.jar &(但windows下沒有,只能在linux或mac下運行實現)
2.自定義返回的業務狀態碼
在utils包下添加JSONData工具類實現
package net.xdclass.demoproject.utils;/*** 接口返回工具類*/
public class JsonData {private int code;private Object data;private String msg;public int getCode() {return code;}public void setCode(int code) {this.code = code;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public JsonData(){}public JsonData(int code, Object data){this.code = code;this.data = data;}public JsonData(int code, Object data, String msg){this.code = code;this.data =data;this.msg = msg;}public static JsonData buildSuccess(Object data){return new JsonData(0,data);}public static JsonData buildError(String msg){return new JsonData(-1,"",msg);}public static JsonData buildError(String msg,int code){return new JsonData(code,"",msg);}@Overridepublic String toString() {return "JsonData{" +"code=" + code +", data=" + data +", msg='" + msg + '\'' +'}';}
}
在controller層中直接調用即可
//將返回的list對象用工具類封裝成json格式的字符串返回給前端
return JsonData.buildSuccess(video);
?3.Jackson
jackson注解,處理相關自動
@JsonIgnore(指定字段不返回)、@JsonFormat(pattern="yyyy-MM-dd hh:mm:ss",locale="zh",timezone="GMT+8")(指定日期格式)、@JsonInclude(Include.NON_NULL)(空字段不返回)、@JsonProperty(指定別名)
序列化和反序列化操作
//序列化操作ObjectMapper objectMapper = new ObjectMapper();String jsonStr = objectMapper.writeValueAsString(list);System.out.println(jsonStr);//反序列化操作List<Video> temp = objectMapper.readValue(jsonStr,List.class);
4.加載配置文件
方式一
- Controller中通過注解指定資源路徑(@PropertySource({"classpath:resource.properties"}))
- 增加屬性@Value("${test.name}") private String name;
方式二:
創建一個實體類配置文件WXConfig
package net.xdclass.demoproject.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;import java.io.Serializable;@Configuration//表示這是一個配置類,用于加載配置文件中的屬性值,會被Spring容器掃描
@PropertySource(value="classpath:pay.properties")
public class WXConfig implements Serializable {@Value("${wxpay.appid}")//從配置文件中獲取屬性值,并賦值給payAppid//或者@Value("${wxpay.appid}")private String payAppid;@Value("${wxpay.secret}")private String paySecret;@Value("${wxpay.mechid}")private String payMechId;public String getPayAppid() {return payAppid;}public void setPayAppid(String payAppid) {this.payAppid = payAppid;}public String getPaySecret() {return paySecret;}public void setPaySecret(String paySecret) {this.paySecret = paySecret;}public String getPayMechId() {return payMechId;}public void setPayMechId(String payMechId) {this.payMechId = payMechId;}
}
在TestController中引入
package net.xdclass.demoproject.controller;import net.xdclass.demoproject.config.WXConfig;
import net.xdclass.demoproject.task.AsyncTask;
import net.xdclass.demoproject.utils.JsonData;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;@RestController
@RequestMapping("api/v1/test")
@PropertySource({"classpath:pay.properties"})//在classpath目錄下查找配置文件的路徑
public class TestController {@Value("${wxpay.appid}")//從配置文件中獲取屬性值,并賦值給payAppid
// @Value("${wxpay.appid}")//方式2private String payAppid;@Value("${wxpay.secret}")private String paySecret;@Autowired//會自動將WXConfig對象注入到TestController對象中private WXConfig wxConfig;@GetMapping("get_config")public JsonData testConfig(){Map<String,String> map = new HashMap<>();
// map.put("appid",payAppid);
// map.put("secret",paySecret);
//
// return JsonData.buildSuccess(map);//通過配置類獲取屬性值,并封裝成map對象返回給前端map.put("appid",wxConfig.getPayAppid());map.put("secret",wxConfig.getPaySecret());map.put("mechid",wxConfig.getPayMechId());return JsonData.buildSuccess(map);//將返回的map對象用工具類封裝成json格式的字符串返回給前端}}
在postman中可通過接口來訪問得到數據,來模擬客戶端
?
5.異常處理
全局異常處理實現
創建一個全局異常處理類
類添加注解
@ControllerAdvice,如果需要返回json數據,則方法需要加@ResponseBody
@RestControllerAdvice, 默認返回json數據,方法不需要加@ResponseBody
方法添加處理器
@ExceptionHandler(value=Exception.class)
package net.xdclass.demoproject.handler;import net.xdclass.demoproject.utils.JsonData;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;/*** 標記這個是一個異常處理類*/
@RestControllerAdvice//標記這個是一個異常處理類,可以處理全局異常
public class CustomExtHandler {//處理特定異常:Exception.class@ExceptionHandler(value = Exception.class)//標記這個方法是一個異常處理方法,處理Exception.class異常JsonData handlerException(Exception e, HttpServletRequest request){//打印異常信息return JsonData.buildError("服務端出問題了", -2);}
}
?自定義全局異常
引入thymeleaf依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
創建異常顯示視圖
resource目錄下新建templates,并新建error.html
創建異常處理類
package net.xdclass.demoproject.handler;import net.xdclass.demoproject.utils.JsonData;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;/*** 標記這個是一個異常處理類*/
@ControllerAdvice//標記這個是一個異常處理類
public class CustomExtHandler {@ExceptionHandler(value = Exception.class)Object handlerException(Exception e, HttpServletRequest request){//打印異常信息:ModelAndView:視圖和模型的結合,可以將數據傳遞給視圖,并渲染視圖ModelAndView modelAndView = new ModelAndView();modelAndView.setViewName("error.html");//設置視圖名稱:error.html,會自動去templates目錄下查找error.html文件,并渲染System.out.println(e.getMessage());//打印異常信息//將異常信息傳遞給視圖modelAndView.addObject("msg",e.getMessage());return modelAndView;}
}
三、優化配置
?1.簡化sql語句
sql片段的使用:select * 去查詢數據庫不適用高并發項目
簡化前
<select id="selectById" parameterType="java.lang.Integer" resultType="Video">select id,title,summary,cover_img from video where id = # {video_id,jdbcType=INTEGER}</select>
簡化后
<sql id="base_video_field">id,title,summary,cover_img</sql><select id="selectById" parameterType="java.lang.Integer" resultType="Video">select <include refid="base_video_field"/> from video where id = # {video_id,jdbcType=INTEGER}</select>
2.查詢操作
復雜查詢
sql的兩種返回類型:resultType(適用于簡單查詢)、resultMap(適用于復雜查詢)?
用resultMap來實現:在xml文件中配置
<!--1.配置映射結果集 2.編寫查詢語句實現查詢-->
<resultMap id="VideoResultMap" type="Video"><!--id 指定查詢列的唯一標示column 數據庫字段的名稱property pojo類的名稱--><id column="id" property="id" jdbcType="INTEGER" /><result column="video_tile" property="title" jdbcType="VARCHAR" /><result column="summary" property="summary" jdbcType="VARCHAR" /><result column="cover_img" property="coverImg" jdbcType="VARCHAR" /></resultMap>
<!--通過配置resultMap將as后面的數據庫類型映射成as前面的java類型 --><select id="selectBaseFieldByIdWithResultMap" resultMap="VideoResultMap">select id , title as video_title, summary, cover_img from video where id = #{video_id}</select>
?在Mapper接口中編寫方法
//復雜查詢Video selectBaseFieldByIdWithResultMap(@Param("video_id")int id);
啟動類中輸出
//resultMap映射出來得到的結果System.out.println(videoMapper.selectBaseFieldByIdWithResultMap(30));
?一對一聯表查詢
當需要同時查詢兩個表的信息時,通過association來配置一對一的關聯表屬性。
xml文件中
<resultMap id="VideoOrderResultMap" type="VideoOrder"><!--配置id為唯一標識--><id column="id" property="id"/><!--配置結果集映射--><result column="user_id" property="userId"/><result column="out_trade_no" property="outTradeNo"/><result column="create_time" property="createTime"/><result column="state" property="state"/><result column="total_fee" property="totalFee"/><result column="video_id" property="videoId"/><result column="video_title" property="videoTitle"/><result column="video_img" property="videoImg"/><!--配置關聯表的映射屬性:association 配置屬性一對一property 對應videoOrder里面的user屬性名javaType 這個屬性的類型--><association property="user" javaType="User"><id property="id" column="user_id"/><result property="name" column="name"/><result property="headImg" column="head_img"/><result property="createTime" column="create_time"/><result property="phone" column="phone"/></association></resultMap><!--一對一管理查詢訂單, 訂單內部包含用戶屬性--><select id="queryVideoOrderList" resultMap="VideoOrderResultMap">selecto.id id,o.user_id ,o.out_trade_no,o.create_time,o.state,o.total_fee,o.video_id,o.video_title,o.video_img,u.name,u.head_img,u.create_time,u.phonefrom video_order o left join user u on o.user_id = u.id</select>
mapper接口
package net.xdclass.online_class.dao;import net.xdclass.online_class.domain.User;
import net.xdclass.online_class.domain.VideoOrder;import java.util.List;public interface VideoOrderMapper {/*** 查詢全部訂單,關聯用戶信息* @return*/List<VideoOrder> queryVideoOrderList();}
啟動類中
// resultmap association關聯查詢VideoOrderMapper videoOrderMapper = sqlSession.getMapper(VideoOrderMapper.class);//獲取mapper對象List<VideoOrder> videoOrderList = videoOrderMapper.queryVideoOrderList();//調用mapper接口中的方法System.out.println(videoOrderList.toString());//輸出結果
一對多聯表查詢
?查詢關聯表信息中的返回多條數據,用collection來實現接收多條數據
<resultMap id="UserOrderResultMap" type="User"><id property="id" column="id"/><result property="name" column="name"/><result property="headImg" column="head_img"/><result property="createTime" column="create_time"/><result property="phone" column="phone"/><!--property 填寫pojo類中集合類屬性的名稱ofType 集合里面的pojo對象--><collection property="videoOrderList" ofType="VideoOrder"><!--配置主鍵,管理order的唯一標識--><id column="order_id" property="id"/><result column="user_id" property="userId"/><result column="out_trade_no" property="outTradeNo"/><result column="create_time" property="createTime"/><result column="state" property="state"/><result column="total_fee" property="totalFee"/><result column="video_id" property="videoId"/><result column="video_title" property="videoTitle"/><result column="video_img" property="videoImg"/></collection></resultMap><select id="queryUserOrder" resultMap="UserOrderResultMap">selectu.id,u.name,u.head_img,u.create_time,u.phone,o.id order_id,o.out_trade_no,o.user_id,o.create_time,o.state,o.total_fee,o.video_id,o.video_title,o.video_imgfrom user u left join video_order o on u.id = o.user_id</select>
小結
?
?