参考资料:老葛课堂
整个项目,葛老师已经上传到他的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;
}
}
***********************************