參考資料:老葛課堂
整個項目,葛老師已經上傳到他的GitHub上面了,GitHub地址為:
http://github.com/gexiangdong/tutorial
使用的的是 maven項目管理、IDEA開發
一、首先看下maven的目錄結構
整個項目結構比較清楚了以后,我們就看一下源代碼。
二、源代碼詳解
首先:源代碼存放的目錄在src/main/java 里面
一共建了以上幾種類
二(1)、Application——啟動類
**************************************************
package cn.devmgr.tutorial;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
*************************************************
就是很簡單的啟動類,是項目的入口
其中注解@SpringBootApplication就是用來聲明:這是一個啟動類
二(2)、TvSeriesController —— RestController的一個例子,展示了各種基本操作在RestController的實現方式。
*****************************************************************************
package cn.devmgr.tutorial;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* RestController的一個例子,展示了各種基本操作在RestController的實現方式。
*
*/
@RestController
@RequestMapping("/tvseries")
public class TvSeriesController {
private final Log log = LogFactory.getLog(TvSeriesController.class);
@GetMapping
public List<TvSeriesDto> getAll() {
if(log.isTraceEnabled()) {
log.trace("getAll() ");
}
List<TvSeriesDto> list = new ArrayList<>();
list.add(createWestWorld());
list.add(createPoi());
return list;
}
@GetMapping("/{id}")
public TvSeriesDto getOne(@PathVariable int id){
if(log.isTraceEnabled()) {
log.trace("getOne " + id);
}
if(id == 101) {
return createWestWorld();
}else if(id == 102) {
return createPoi();
}else {
throw new ResourceNotFoundException();
}
}
/**
* @Valid 注解表示需要驗證傳入的參數TvSeriesDto,需要驗證的field在TvSeriesDto內通過注解定義(@NotNull, @DecimalMin等)
* @param tvSeriesDto
* @return
*/
@PostMapping
public TvSeriesDto insertOne(@Valid @RequestBody TvSeriesDto tvSeriesDto) {
if(log.isTraceEnabled()) {
log.trace("這里應該寫新增tvSeriesDto到數據庫的代碼, 傳遞進來的參數是:" + tvSeriesDto);
}
//TODO:在數據
tvSeriesDto.setId(9999);
return tvSeriesDto;
}
/**
*
* @param id
* @param tvSeriesDto
* @return
*/
@PutMapping("/{id}")
public TvSeriesDto updateOne(@PathVariable int id, @RequestBody TvSeriesDto tvSeriesDto){
if(log.isTraceEnabled()) {
log.trace("updateOne " + id);
}
if(id == 101 || id == 102) {
//TODO: 根據tvSeriesDto的內容更新數據庫,更新后返回新
return createPoi();
}else {
throw new ResourceNotFoundException();
}
}
/**
* 刪除資源的例子;如果方法聖母了HttpServletRequest request參數,spring會自動把當前的request傳給方法。
* 類似聲明即可得到還有 HttpServletResponse,Authentication、Locale等
*
* @RequestParam(value="delete_reason", required=false) String deleteReason 表示deleteReason參數的值
* 來自Request的參數delete_reason(等同於request.getParameter("delete_reason"),可以是URL中Querystring,
* 也可以是form post里的值),required=false表示不是必須的。默認是required=true,required=true時,如果請求
* 沒有傳遞這個參數,會被返回400錯誤。
* 類似的注解還有@CookieValue @RequestHeader等。
*/
@DeleteMapping("/{id}")
public Map<String, String> deleteOne(@PathVariable int id, HttpServletRequest request,
@RequestParam(value="delete_reason", required=false) String deleteReason) throws Exception{
if(log.isTraceEnabled()) {
log.trace("deleteOne " + id);
}
Map<String, String> result = new HashMap<>();
if(id == 101) {
//TODO: 執行刪除的代碼
result.put("message", "#101被" + request.getRemoteAddr() + "刪除(原因:" + deleteReason + ")");
}else if(id == 102) {
//不能刪除這個,RuntimeException不如org.springframework.security.access.AccessDeniedException更合適
//但此處還沒到spring security,所以暫先拋出RuntimeException異常
throw new RuntimeException("#102不能刪除");
}else {
//不存在
throw new ResourceNotFoundException();
}
return result;
}
/**
* 給電視劇添加劇照。
* 這是一個文件上傳的例子(具體上傳處理代碼沒有寫)
* @param id
* @param imgFile
* @throws Exception
*/
@PostMapping(value="/{id}/photos", consumes=MediaType.MULTIPART_FORM_DATA_VALUE)
public void addPhoto(@PathVariable int id, @RequestParam("photo") MultipartFile imgFile) throws Exception{
if(log.isTraceEnabled()) {
log.trace("接受到文件 " + id + "收到文件:" + imgFile.getOriginalFilename());
}
//保存文件
FileOutputStream fos = new FileOutputStream("target/" + imgFile.getOriginalFilename());
IOUtils.copy(imgFile.getInputStream(), fos);
fos.close();
}
/**
* 返回某電視劇的圖標
* 這是一個返回非JSON格式(圖片)格式的例子
* @param id
* @return
*/
@GetMapping(value="/{id}/icon", produces=MediaType.IMAGE_JPEG_VALUE)
public byte[] getIcon(@PathVariable int id) throws Exception{
if(log.isTraceEnabled()) {
log.trace("getIcon(" + id + ")");
}
String iconFile = "src/test/resources/icon.jpg";
InputStream is = new FileInputStream(iconFile);
byte[] data = IOUtils.toByteArray(is);
is.close();
return data;
}
/**
* 創建電視劇“Person of Interest",僅僅方便此節做展示其他方法用,以后章節把數據存儲到數據庫后,會刪除此方法
*/
private TvSeriesDto createPoi() {
Calendar c = Calendar.getInstance();
c.set(2011, Calendar.SEPTEMBER, 22, 0, 0, 0);
return new TvSeriesDto(102, "Person of Interest", 5, c.getTime());
}
/**
* 創建電視劇“West World",僅僅方便此節做展示其他方法用,以后章節把數據存儲到數據庫后,會刪除此方法
*/
private TvSeriesDto createWestWorld() {
Calendar c = Calendar.getInstance();
c.set(2016, Calendar.OCTOBER, 2, 0, 0, 0);
return new TvSeriesDto(101, "West World", 1, c.getTime());
}
}
***************** *********************************************************************
@RestController 該注解表示請求資源
@RequestMapping 該注解表示請求資源的url
按本例中,應在瀏覽器中輸入:http://locolhost:8080/tvseries
@GetMapping 該注解表示獲取資源。
首先添加日志,然后獲取資源。
其他方法也都差不多,所以我暫時不講,有看不懂的可以留言問我
二(3)、TvCharacterDto、TvSeriesDto
TvCharacterDto:
**********************************
package cn.devmgr.tutorial;
import javax.validation.constraints.NotNull;
public class TvCharacterDto {
private Integer id;
private int tvSeriesId;
@NotNull private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public int getTvSeriesId() {
return tvSeriesId;
}
public void setTvSeriesId(int tvSeriesId) {
this.tvSeriesId = tvSeriesId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
**********************************
TvSeriesDto:
**********************************
package cn.devmgr.tutorial;
import java.util.Date;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 基本的POJO,而且使用Bean Validation注解進行校驗數據
* @author gexiangdong
*
*/
public class TvSeriesDto {
@Null private Integer id;
@NotNull private String name;
@DecimalMin("1") private int seasonCount;
//@Valid表示要級聯校驗;@Size(min=2)表示這個列表至少要有2項內容,否則通不過校驗
@Valid @NotNull @Size(min=2) private List<TvCharacterDto> tvCharacters;
//如果想用long型的timestamp表示日期,可用: @JsonFormat(shape = JsonFormat.Shape.NUMBER)
@JsonFormat(timezone="GMT+8", pattern="yyyy-MM-dd")
//@Past表示只接受過去的時間,比當前時間還晚的被認為不合格
@Past private Date originRelease;
public TvSeriesDto() {
}
public TvSeriesDto(int id, String name, int seasonCount, Date originRelease) {
this.id = id;
this.name = name;
this.seasonCount = seasonCount;
this.originRelease = originRelease;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSeasonCount() {
return seasonCount;
}
public void setSeasonCount(int seasonCount) {
this.seasonCount = seasonCount;
}
public Date getOriginRelease() {
return originRelease;
}
public void setOriginRelease(Date originRelease) {
this.originRelease = originRelease;
}
public List<TvCharacterDto> getTvCharacters() {
return tvCharacters;
}
public void setTvCharacters(List<TvCharacterDto> tvCharacters) {
this.tvCharacters = tvCharacters;
}
}
***********************************