| 知乎專欄 | 多維度架構 | | | 微信號 netkiller-ebook | | | QQ群:128659835 請註明“讀者” |
@RequestMapping("/get/{id}")
public Member getStatistics(@PathVariable long id) {
Member statistics = memberRepostitory.findOne(id);
if (statistics == null) {
statistics = new Member();
}
return statistics;
}
MediaType.APPLICATION_JSON_VALUE 執行結果反饋json數據
@RestController
@RequestMapping("/api/persons")
public class MainController {
@RequestMapping(
value = "/detail/{id}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<Persons> getUserDetail(@PathVariable Long id) {
Persons user = personsRepository.findById(id);
return new ResponseEntity<>(user, HttpStatus.OK);
}
}
@RequestMapping(value = "/create", method = RequestMethod.POST, produces = { "application/xml", "application/json" })
public ResponseEntity<Member> create(@RequestBody Member member) {
memberRepository.save(member);
return new ResponseEntity<Member>(member, HttpStatus.OK);
}
package api.config;
import java.io.IOException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
@Configuration
public class JacksonConfig {
@Bean
@Primary
@ConditionalOnMissingBean(ObjectMapper.class)
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
jsonGenerator.writeString("");
}
});
return objectMapper;
}
}
restful 將同時支持 json 和 xml 數據傳遞
package com.example.api.restful;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.example.api.domain.RecentRead;
import com.example.api.repository.RecentReadRepostitory;
@RestController
@RequestMapping("/restful/article")
public class ArticleRestController {
@Autowired
private RecentReadRepostitory recentReadRepostitory;
@RequestMapping(value = "/recent/read/add/{memberId}/{articleId}", method = RequestMethod.GET, produces = { "application/xml", "application/json" })
public ResponseEntity<RecentRead> recentAdd(@PathVariable long memberId, @PathVariable long articleId) {
RecentRead recentRead = new RecentRead();
recentRead.setMemberId(memberId);
recentRead.setArticleId(articleId);
recentReadRepostitory.save(recentRead);
return new ResponseEntity<RecentRead>(recentRead, HttpStatus.OK);
}
@RequestMapping(value="/recent/read/list/{id}", produces = { "application/xml", "application/json" })
public List<RecentRead> recentList(@PathVariable long id) {
int page = 0;
int limit = 20;
List<RecentRead> recentRead = recentReadRepostitory.findByMemberId(id, new PageRequest(page, limit));
return recentRead;
}
}
開發中發現很多人不適應新的介面方式,有時候只能妥協,這些頑固不化的人需要這樣的資料庫格式
{
"status":true,
"reason":"登錄成功",
"code":1,
"data":{
"id":2,
"name":null,
"sex":null,
"age":0,
"wechat":null,
"mobile":"13113668890",
"picture":null,
"ipAddress":"0:0:0:0:0:0:0:1"
}
}
返回數據必須放在 data 字典中, 而我通常是採用 http status code 來返回狀態,返回結果是對象。實現上面的需求我們需要加入一個data成員變數,因為我們不清楚最終要返回什麼對象。所以聲明為 java.lang.Object
package com.example.api.pojo;
import java.io.Serializable;
public class RestfulResponse implements Serializable {
/**
*
*/
private static final long serialVersionUID = -4045645995352698349L;
private boolean status;
private String reason;
private int code;
private Object data;
public RestfulResponse(boolean status, int code, String reason, Object data) {
this.status = status;
this.code = code;
this.reason = reason;
this.data = data;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
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;
}
@Override
public String toString() {
return "RestfulResponse [status=" + status + ", reason=" + reason + ", code=" + code + ", data=" + data + "]";
}
}
Service
public RestfulResponse bindWechat(String mobile, String wechat) {
Member member = memberRepository.findByMobile(mobile);
member.setWechat(wechat);
memberRepository.save(member);
return new RestfulResponse(true, 1, "微信綁定成功", member);
}
Controller
@RequestMapping("/login/sms/{mobile}/{code}")
public RestfulResponse sms(@PathVariable String mobile, @PathVariable String wechat) {
return memberService.bindWechat(mobile, wechat);
}
@RequestMapping(value = "/list", method=RequestMethod.GET)
public Page<Blog> getEntryByPageable1(@PageableDefault( sort = { "id" }, direction = Sort.Direction.DESC)
Pageable pageable) {
return blogRepository.findAll(pageable);
}
@RequestMapping(value = "/blog", method=RequestMethod.GET)
public Page<Blog> getEntryByPageable(@PageableDefault(value = 15, sort = { "id" }, direction = Sort.Direction.DESC)
Pageable pageable) {
return blogRepository.findAll(pageable);
}
@RequestMapping(value = "/list", method=RequestMethod.GET)
public Page<Blog> getEntryByPageable2(@PageableDefault Pageable pageable) {
return blogRepository.findAll(pageable);
}
@ModelAttribute("users")
public Page<User> users(@PageableDefault(size = 5) Pageable pageable) {
return userManagement.findAll(pageable);
}
我們只需要在方法的參數中直接定義一個pageable類型的參數,當Spring發現這個參數時,Spring會自動的根據request的參數來組裝該pageable對象,Spring支持的request參數如下:
page,第幾頁,從0開始,預設為第0頁
size,每一頁的大小,預設為20
sort,排序相關的信息,以property,property(,ASC|DESC)的方式組織,例如sort=firstname&sort=lastname,desc表示在按firstname正序排列基礎上按lastname倒序排列
這樣,我們就可以通過url的參數來進行多樣化、個性化的查詢,而不需要為每一種情況來寫不同的方法了。
通過url來定製pageable很方便,但唯一的缺點是不太美觀,因此我們需要為pageable設置一個預設配置,這樣很多情況下我們都能夠通過一個簡潔的url來獲取信息了。
Spring提供了@PageableDefault幫助我們個性化的設置pageable的預設配置。例如@PageableDefault(value = 15, sort = { "id" }, direction = Sort.Direction.DESC)表示預設情況下我們按照id倒序排列,每一頁的大小為15。
spring.servlet.multipart.max-file-size=128KB spring.servlet.multipart.max-request-size=128KB spring.http.multipart.enabled=false
RestController
package api.restful;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.springframework.web.bind.annotation.PostMapping;
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;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import api.pojo.RestfulResponse;
@RestController
@RequestMapping("/upload")
public class UploadRestController {
private final static String FOLDER = "/tmp";
public UploadRestController() {
}
@PostMapping("/single")
public RestfulResponse upload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
if (file.isEmpty()) {
return new RestfulResponse(false, 0, "Please select a file to upload", "");
}
try {
byte[] bytes = file.getBytes();
Path path = Paths.get(FOLDER + "/" + file.getOriginalFilename());
Files.write(path, bytes);
return new RestfulResponse(true, 0, "", path.toString());
} catch (Exception e) {
return new RestfulResponse(false, 0, e.getMessage(), null);
}
}
@PostMapping(value = "/group")
public RestfulResponse group(@RequestParam("files") MultipartFile[] files) {
List<String> filelist = new ArrayList<String>();
try {
for (MultipartFile file : files) {
File tmpfile = new File(FOLDER + "/" + file.getOriginalFilename());
file.transferTo(tmpfile);
filelist.add(tmpfile.getPath());
}
return new RestfulResponse(true, 0, null, filelist);
} catch (Exception e) {
return new RestfulResponse(false, 0, e.getMessage(), null);
}
}
}
由於上傳檔案名可能存在空格等特殊字元,這裡使用UUID替代檔案名
@PostMapping(value = "/file")
public RestfulResponse file(@RequestParam("file") MultipartFile[] files) {
List<Object> filelist = new ArrayList<Object>();
try {
for (MultipartFile file : files) {
UUID uuid = UUID.randomUUID();
String filename = String.format("%s/%s.%s", folder, uuid.toString(), this.getExtensionName(filename));
File tmpfile = new File(filename);
String filepath = tmpfile.getPath();
System.out.println(filepath);
file.transferTo(tmpfile);
filelist.add(tmpfile.toString());
}
return new RestfulResponse(true, 0, null, filelist);
} catch (Exception e) {
return new RestfulResponse(false, 0, e.getMessage(), null);
}
}
private String getExtensionName(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot > -1) && (dot < (filename.length() - 1))) {
return filename.substring(dot + 1);
}
}
return filename;
}