This content originally appeared on DEV Community and was authored by DEV Community
Spring boot
Client Side
以下 Entity 會以自動產生的方式給予 PR
EntityController 則是底層功能
Entity Model
@Entity
@Table(name = "CAR")
public class Car extends EntityContoller {
@Id
@Column(name = "ID")
@SerializedName("ID")
private Integer id;
@Column(name = "MODEL")
@SerializedName("MODEL")
private String model;
@Column(name = "MAKE")
@SerializedName("MAKE")
private String make;
@Column(name = "PREVIEW")
@SerializedName("PREVIEW")
private String preview;
@Column(name = "DESCRIPTION")
@SerializedName("DESCRIPTION")
private String description;
@Column(name = "PRICE")
@SerializedName("PRICE")
private Integer price;
public Car() {
super();
}
public Car(Integer id, String model, String make, String description, String preview, Integer price) {
super();
this.id = id;
this.model = model;
this.make = make;
this.preview = preview;
this.description = description;
this.price = price;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getPreview() {
return preview;
}
public void setPreview(String preview) {
this.preview = preview;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
}
@Entity
@Table(name = "CAR_INFO")
public class CarInfo extends EntityContoller {
@Id
@SerializedName("ID")
@Column(name = "ID")
private Integer id;
@Id
@SerializedName("CAR_OWNER")
@Column(name = "CAR_OWNER")
private String carOwner;
@Column(name = "CAR_TYPE")
@SerializedName("CAR_TYPE")
private String carType;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "DRIVE_DATE")
@SerializedName("DRIVE_DATE")
private Date driveDate;
@Column(name = "KM")
@SerializedName("KM")
private String km;
@Column(name = "TEST")
@SerializedName("TEST")
private String test;
@ManyToOne
@SerializedName("*CAR")
@JoinColumn(name = "ID", referencedColumnName = "ID", insertable = false, updatable = false)
private Car car = new Car();
public CarInfo() {
super();
}
public CarInfo(Integer id, String carOwner, String carType, Date driveDate, String km, String test, Car car) {
super();
this.id = id;
this.carOwner = carOwner;
this.carType = carType;
this.driveDate = driveDate;
this.km = km;
this.test = test;
this.car = car;
}
public Integer getId() {
return id;
}
public void setId(Integer value) {
id = value;
}
public String getCarOwner() {
return carOwner;
}
public void setCarOwner(String value) {
carOwner = value;
}
public Date getDriveDate() {
return driveDate;
}
public void setDriveDate(Date value) {
driveDate = value;
}
public String getKm() {
return km;
}
public void setKm(String value) {
km = value;
}
public String getTest() {
return test;
}
public void setTest(String value) {
test = value;
}
public String getCarType() {
return carType;
}
public void setCarType(String value) {
carType = value;
}
public Car getCar() {
return car;
}
public void setCar(Car value) {
car = value;
}
}
ViewModel
public class CarInfoViewModel extends ServiceImpl {
private String keyword;
private List<CarInfo> list;
private CarInfo selectedCarInfo;
private CarService carService = new CarServiceImpl();
public CarInfoViewModel() {
super(new CarInfo());
}
public List<CarInfo> getList(){
return list;
}
public void setSelectedCarInfo(CarInfo selectedCarInfo) {
this.selectedCarInfo = selectedCarInfo;
}
public CarInfo getSelectedCarInfo() {
return selectedCarInfo;
}
@Command
@NotifyChange("list")
public void search(){
list = carService.search(keyword);
}
public List<CarInfo> get {
RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), gson.toJson(new CarInfo()));
retrofit2.Call<ResponseBody> call = entityServices.getNativeCarInfo(body);
Type type = new TypeToken<List<CarInfo>>() {}.getType();
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
list = gson.fromJson(response.body().string(), type);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
System.out.println("Connection Failed");
}
});
}
}
View
<window title="Search" width="600px" border="normal" apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('demo.getting_started.mvvm.SearchViewModel')">
<hbox align="center">
Keyword:
<textbox value="@bind(vm.keyword)" />
<button label="Search" iconSclass="z-icon-search" onClick="@command('search')" />
</hbox>
<listbox height="160px" model="@bind(vm.carInfoList)" emptyMessage="No car found in the result"
selectedItem="@bind(vm.selectedCarInfo)" style="margin-top:10px">
<listhead>
<listheader label="ID" />
<listheader label="Car Owner" />
<listheader label="Car Type" />
<listheader label="Drive Date" />
<listheader label="KM" />
</listhead>
<template name="model">
<listitem>
<listcell label="@bind(each.id)"></listcell>
<listcell label="@bind(each.carOwner)"></listcell>
<listcell label="@bind(each.carType)"></listcell>
<listcell label="@bind(each.driveDate) @converter('formatedDate',format='yyyy/MM/dd')"></listcell>
<listcell label="@bind(each.km)"></listcell>
</listitem>
</template>
</listbox>
<hbox style="margin-top:20px" visible="@bind(not empty vm.selectedCarInfo)">
<image src="@bind(vm.selectedCarInfo.car.preview)" style="padding:10px" />
<vbox>
<hlayout>
Model : <label value="@bind(vm.selectedCarInfo.car.model)" style="font-weight:bold"/>
</hlayout>
<hlayout>
Make : <label value="@bind(vm.selectedCarInfo.car.make)" style="font-weight:bold"/>
</hlayout>
<hlayout>
Price :
<span>$<label value="@bind(vm.selectedCarInfo.car.price)" style="font-weight:bold"/></span>
</hlayout>
<label value="@bind(vm.selectedCarInfo.car.description)" />
</vbox>
</hbox>
</window>
Server Side
PR 如需複雜方式必須去 Spring Boot 新增,並將 Entity Model 放入Spring Boot
CarInfoContoller
@RestController
@RequestMapping("/carinfo")
public class CarInfoContoller {
@Autowired
private CarInfoRepository carInfoRepository;
@Autowired
CarInfoService CarInfoService;
@GetMapping("/paging") // native sql
public List<CarInfo> getCarInfoByNativeSQL(@PageableDefault(size = 10) Pageable pageable) {
Page<CarInfo> contacts = this.carInfoRepository.findAllUsersWithPaginationByNativeSQL(pageable);
return contacts.getContent();
}
}
@Repository
public interface CarInfoRepository extends JpaRepository<CarInfo, Long> {
@Query(value = "SELECT * FROM CarInfo ORDERBY CAR_OWNER", countQuery = "SELECT count(*) FROM CarInfo", nativeQuery = true)
Page<CarInfo> findAllUsersWithPaginationByNativeSQL(Pageable pageable);
}
JpaRepository 支援關鍵字方法語法
Keyword | Sample | JPQL snippet |
---|---|---|
And | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |
Or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
Between | findByStartDateBetween | … where x.startDate between 1? and ?2 |
LessThan | findByAgeLessThan | … where x.age < ?1 |
GreaterThan | findByAgeGreaterThan | … where x.age > ?1 |
After | findByStartDateAfter | … where x.startDate > ?1 |
Before | findByStartDateBefore | … where x.startDate < ?1 |
IsNull | findByAgeIsNull | … where x.age is null |
IsNotNull,NotNull | findByAge(Is)NotNull | … where x.age not null |
Like | findByFirstnameLike | … where x.firstname like ?1 |
NotLike | findByFirstnameNotLike | … where x.firstname not like ?1 |
StartingWith | findByFirstnameStartingWith | … where x.firstname like ?1 (parameter bound with appended %) |
EndingWith | findByFirstnameEndingWith | … where x.firstname like ?1 (parameter bound with prepended %) |
Containing | findByFirstnameContaining | … where x.firstname like ?1 (parameter bound wrapped in %) |
OrderBy | findByAgeOrderByLastnameDesc | … where x.age = ?1 order by x.lastname desc |
Not | findByLastnameNot | … where x.lastname <> ?1 |
In | findByAgeIn( |
Collection<Age> ages
)|… where x.age in ?1 |
| NotIn| findByAgeNotIn(
Collection<Age> age
)|… where x.age not in ?1 |
| True| findByActiveTrue()|… where x.active = true |
| False| findByActiveFalse()|… where x.active = false |
gRPC
#透過 protoc tool 產生code
$ protoc -I car_info/ car_info/car_info.proto --go_out=plugins=grpc:car_info
#透過 maven plugin 產生code
$ mvn protobuf:compile
Golang Service Side
syntax = "proto3";
// 生成的程式在 Golang 中將會屬於 `pb` 套件。
option java_multiple_files = true;
option java_package = "io.grpc.examples.car_info";
option java_outer_classname = "CarInfoProto";
option objc_class_prefix = "CARINFO";
package car_info;
// CarInfo 定義了一個服務。
service CarInfoService {
// GetList 會接收 CarInfoGetListRequest 資料,最終會回傳 CarInfoGetListResponse
rpc GetList (CarInfoGetListRequest) returns (CarInfoGetListResponse) {}
rpc InsertList (CarInfoInsertListRequest) returns (CarInfoInsertListResponse) {}
}
message CarInfo {
string CarOwner = 1;
string CarType = 2;
string DriveDate = 3;
string km = 4;
string test = 5;
}
// Car Info Get List 需求 list
message CarInfoGetListRequest { }
// Car Info Get List 回應 list
message CarInfoGetListResponse {
repeated CarInfo cars = 1;
}
// Car Info Get List 需求list
message CarInfoInsertListRequest {
repeated CarInfo cars = 1;
}
// Car Info Get List 回應 list
message CarInfoInsertListResponse {
repeated CarInfo cars = 1;
}
透過工具產生 code go 版本
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: car_info.proto
package car_info
import (
context "context"
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type CarInfo struct {
CarOwner string `protobuf:"bytes,1,opt,name=CarOwner,proto3" json:"CarOwner,omitempty"`
CarType string `protobuf:"bytes,2,opt,name=CarType,proto3" json:"CarType,omitempty"`
DriveDate string `protobuf:"bytes,3,opt,name=DriveDate,proto3" json:"DriveDate,omitempty"`
Km string `protobuf:"bytes,4,opt,name=km,proto3" json:"km,omitempty"`
Test string `protobuf:"bytes,5,opt,name=test,proto3" json:"test,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CarInfo) Reset() { *m = CarInfo{} }
func (m *CarInfo) String() string { return proto.CompactTextString(m) }
func (*CarInfo) ProtoMessage() {}
func (*CarInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_6109e1b82e86989a, []int{0}
}
func (m *CarInfo) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CarInfo.Unmarshal(m, b)
}
func (m *CarInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CarInfo.Marshal(b, m, deterministic)
}
func (m *CarInfo) XXX_Merge(src proto.Message) {
xxx_messageInfo_CarInfo.Merge(m, src)
}
func (m *CarInfo) XXX_Size() int {
return xxx_messageInfo_CarInfo.Size(m)
}
func (m *CarInfo) XXX_DiscardUnknown() {
xxx_messageInfo_CarInfo.DiscardUnknown(m)
}
var xxx_messageInfo_CarInfo proto.InternalMessageInfo
func (m *CarInfo) GetCarOwner() string {
if m != nil {
return m.CarOwner
}
return ""
}
func (m *CarInfo) GetCarType() string {
if m != nil {
return m.CarType
}
return ""
}
func (m *CarInfo) GetDriveDate() string {
if m != nil {
return m.DriveDate
}
return ""
}
func (m *CarInfo) GetKm() string {
if m != nil {
return m.Km
}
return ""
}
func (m *CarInfo) GetTest() string {
if m != nil {
return m.Test
}
return ""
}
// Car Info Get List 需求 list
type CarInfoGetListRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CarInfoGetListRequest) Reset() { *m = CarInfoGetListRequest{} }
func (m *CarInfoGetListRequest) String() string { return proto.CompactTextString(m) }
func (*CarInfoGetListRequest) ProtoMessage() {}
func (*CarInfoGetListRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_6109e1b82e86989a, []int{1}
}
func (m *CarInfoGetListRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CarInfoGetListRequest.Unmarshal(m, b)
}
func (m *CarInfoGetListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CarInfoGetListRequest.Marshal(b, m, deterministic)
}
func (m *CarInfoGetListRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_CarInfoGetListRequest.Merge(m, src)
}
func (m *CarInfoGetListRequest) XXX_Size() int {
return xxx_messageInfo_CarInfoGetListRequest.Size(m)
}
func (m *CarInfoGetListRequest) XXX_DiscardUnknown() {
xxx_messageInfo_CarInfoGetListRequest.DiscardUnknown(m)
}
var xxx_messageInfo_CarInfoGetListRequest proto.InternalMessageInfo
// Car Info Get List 回應 list
type CarInfoGetListResponse struct {
Cars []*CarInfo `protobuf:"bytes,1,rep,name=cars,proto3" json:"cars,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CarInfoGetListResponse) Reset() { *m = CarInfoGetListResponse{} }
func (m *CarInfoGetListResponse) String() string { return proto.CompactTextString(m) }
func (*CarInfoGetListResponse) ProtoMessage() {}
func (*CarInfoGetListResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_6109e1b82e86989a, []int{2}
}
func (m *CarInfoGetListResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CarInfoGetListResponse.Unmarshal(m, b)
}
func (m *CarInfoGetListResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CarInfoGetListResponse.Marshal(b, m, deterministic)
}
func (m *CarInfoGetListResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_CarInfoGetListResponse.Merge(m, src)
}
func (m *CarInfoGetListResponse) XXX_Size() int {
return xxx_messageInfo_CarInfoGetListResponse.Size(m)
}
func (m *CarInfoGetListResponse) XXX_DiscardUnknown() {
xxx_messageInfo_CarInfoGetListResponse.DiscardUnknown(m)
}
var xxx_messageInfo_CarInfoGetListResponse proto.InternalMessageInfo
func (m *CarInfoGetListResponse) GetCars() []*CarInfo {
if m != nil {
return m.Cars
}
return nil
}
type CarInfoInsertListRequest struct {
Cars []*CarInfo `protobuf:"bytes,1,rep,name=cars,proto3" json:"cars,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CarInfoInsertListRequest) Reset() { *m = CarInfoInsertListRequest{} }
func (m *CarInfoInsertListRequest) String() string { return proto.CompactTextString(m) }
func (*CarInfoInsertListRequest) ProtoMessage() {}
func (*CarInfoInsertListRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_6109e1b82e86989a, []int{3}
}
func (m *CarInfoInsertListRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CarInfoInsertListRequest.Unmarshal(m, b)
}
func (m *CarInfoInsertListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CarInfoInsertListRequest.Marshal(b, m, deterministic)
}
func (m *CarInfoInsertListRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_CarInfoInsertListRequest.Merge(m, src)
}
func (m *CarInfoInsertListRequest) XXX_Size() int {
return xxx_messageInfo_CarInfoInsertListRequest.Size(m)
}
func (m *CarInfoInsertListRequest) XXX_DiscardUnknown() {
xxx_messageInfo_CarInfoInsertListRequest.DiscardUnknown(m)
}
var xxx_messageInfo_CarInfoInsertListRequest proto.InternalMessageInfo
func (m *CarInfoInsertListRequest) GetCars() []*CarInfo {
if m != nil {
return m.Cars
}
return nil
}
// Car Info Get List 回應 list
type CarInfoInsertListResponse struct {
Cars []*CarInfo `protobuf:"bytes,1,rep,name=cars,proto3" json:"cars,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CarInfoInsertListResponse) Reset() { *m = CarInfoInsertListResponse{} }
func (m *CarInfoInsertListResponse) String() string { return proto.CompactTextString(m) }
func (*CarInfoInsertListResponse) ProtoMessage() {}
func (*CarInfoInsertListResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_6109e1b82e86989a, []int{4}
}
func (m *CarInfoInsertListResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CarInfoInsertListResponse.Unmarshal(m, b)
}
func (m *CarInfoInsertListResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CarInfoInsertListResponse.Marshal(b, m, deterministic)
}
func (m *CarInfoInsertListResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_CarInfoInsertListResponse.Merge(m, src)
}
func (m *CarInfoInsertListResponse) XXX_Size() int {
return xxx_messageInfo_CarInfoInsertListResponse.Size(m)
}
func (m *CarInfoInsertListResponse) XXX_DiscardUnknown() {
xxx_messageInfo_CarInfoInsertListResponse.DiscardUnknown(m)
}
var xxx_messageInfo_CarInfoInsertListResponse proto.InternalMessageInfo
func (m *CarInfoInsertListResponse) GetCars() []*CarInfo {
if m != nil {
return m.Cars
}
return nil
}
func init() {
proto.RegisterType((*CarInfo)(nil), "car_info.CarInfo")
proto.RegisterType((*CarInfoGetListRequest)(nil), "car_info.CarInfoGetListRequest")
proto.RegisterType((*CarInfoGetListResponse)(nil), "car_info.CarInfoGetListResponse")
proto.RegisterType((*CarInfoInsertListRequest)(nil), "car_info.CarInfoInsertListRequest")
proto.RegisterType((*CarInfoInsertListResponse)(nil), "car_info.CarInfoInsertListResponse")
}
func init() { proto.RegisterFile("car_info.proto", fileDescriptor_6109e1b82e86989a) }
var fileDescriptor_6109e1b82e86989a = []byte{
// 309 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x52, 0xdd, 0x4a, 0x02, 0x41,
0x14, 0x6e, 0x56, 0x4b, 0x3d, 0x85, 0xd0, 0x81, 0x6a, 0x94, 0x20, 0xd9, 0x08, 0xbc, 0xda, 0x0b,
0xa3, 0xeb, 0xf0, 0x87, 0x42, 0x08, 0x95, 0x2d, 0xe8, 0x32, 0xa6, 0xe5, 0x18, 0x8b, 0xb9, 0xb3,
0xcd, 0x4c, 0x56, 0x97, 0xbd, 0x4a, 0x6f, 0xd1, 0xdb, 0x85, 0xd3, 0xb8, 0x56, 0x5b, 0x51, 0x77,
0x73, 0xbe, 0x3f, 0xbe, 0x33, 0x1c, 0xa8, 0x46, 0x42, 0x5d, 0xc5, 0xc9, 0x58, 0x06, 0xa9, 0x92,
0x46, 0x62, 0x79, 0x31, 0xfb, 0xcf, 0x0c, 0x4a, 0x5d, 0xa1, 0xfa, 0xc9, 0x58, 0x62, 0x1d, 0xca,
0x5d, 0xa1, 0x86, 0x0f, 0x09, 0x29, 0xce, 0x1a, 0xac, 0x59, 0x09, 0xb3, 0x19, 0xb9, 0x95, 0x5d,
0x3c, 0xa5, 0xc4, 0x3d, 0x4b, 0x2d, 0x46, 0xdc, 0x85, 0x4a, 0x4f, 0xc5, 0x33, 0xea, 0x09, 0x43,
0xbc, 0x60, 0xb9, 0x25, 0x80, 0x55, 0xf0, 0x26, 0x53, 0x5e, 0xb4, 0xb0, 0x37, 0x99, 0x22, 0x42,
0xd1, 0x90, 0x36, 0x7c, 0xd5, 0x22, 0xf6, 0xed, 0xef, 0xc0, 0x96, 0xab, 0x70, 0x4a, 0xe6, 0x2c,
0xd6, 0x26, 0xa4, 0xbb, 0xfb, 0x39, 0x71, 0x0c, 0xdb, 0x5f, 0x09, 0x9d, 0xca, 0x44, 0x13, 0x1e,
0x40, 0x31, 0x12, 0x4a, 0x73, 0xd6, 0x28, 0x34, 0xd7, 0x5b, 0x9b, 0x41, 0xb6, 0x9f, 0xd3, 0x87,
0x96, 0xf6, 0xdb, 0xc0, 0x1d, 0xd0, 0x4f, 0x34, 0xa9, 0x8f, 0xe1, 0x7f, 0x8d, 0xe8, 0x40, 0xed,
0x9b, 0x88, 0x7f, 0xd5, 0x68, 0xbd, 0x32, 0xa8, 0x3a, 0xe4, 0x9c, 0xd4, 0x2c, 0x8e, 0x08, 0x07,
0x50, 0x72, 0x3b, 0xe1, 0x5e, 0xce, 0xf6, 0xf9, 0x1b, 0xea, 0x8d, 0x9f, 0x05, 0xef, 0x3d, 0xfc,
0x15, 0xbc, 0x04, 0x58, 0xf6, 0x43, 0x3f, 0xe7, 0xc8, 0xed, 0x5f, 0xdf, 0xff, 0x55, 0xb3, 0x08,
0xee, 0x1c, 0x41, 0x2d, 0x96, 0xc1, 0x8d, 0x4a, 0xa3, 0x80, 0x1e, 0xc5, 0x34, 0xbd, 0x25, 0x9d,
0x19, 0x3b, 0x1b, 0xce, 0x39, 0x9a, 0x5f, 0xd5, 0x88, 0xbd, 0x78, 0xa5, 0x6e, 0x3b, 0xec, 0x0f,
0x4e, 0x86, 0xd7, 0x6b, 0xf6, 0xd0, 0x0e, 0xdf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x22, 0xe2, 0x10,
0xb0, 0x7a, 0x02, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// CarInfoServiceClient is the client API for CarInfoService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type CarInfoServiceClient interface {
// GetList 會接收 CarInfoGetListRequest 資料,最終會回傳 CarInfoGetListResponse
GetList(ctx context.Context, in *CarInfoGetListRequest, opts ...grpc.CallOption) (*CarInfoGetListResponse, error)
// rpc GetList (CarInfoGetListRequest) returns (stream CarInfo) {}
InsertList(ctx context.Context, in *CarInfoInsertListRequest, opts ...grpc.CallOption) (*CarInfoInsertListResponse, error)
}
type carInfoServiceClient struct {
cc *grpc.ClientConn
}
func NewCarInfoServiceClient(cc *grpc.ClientConn) CarInfoServiceClient {
return &carInfoServiceClient{cc}
}
func (c *carInfoServiceClient) GetList(ctx context.Context, in *CarInfoGetListRequest, opts ...grpc.CallOption) (*CarInfoGetListResponse, error) {
out := new(CarInfoGetListResponse)
err := c.cc.Invoke(ctx, "/car_info.CarInfoService/GetList", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *carInfoServiceClient) InsertList(ctx context.Context, in *CarInfoInsertListRequest, opts ...grpc.CallOption) (*CarInfoInsertListResponse, error) {
out := new(CarInfoInsertListResponse)
err := c.cc.Invoke(ctx, "/car_info.CarInfoService/InsertList", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// CarInfoServiceServer is the server API for CarInfoService service.
type CarInfoServiceServer interface {
// GetList 會接收 CarInfoGetListRequest 資料,最終會回傳 CarInfoGetListResponse
GetList(context.Context, *CarInfoGetListRequest) (*CarInfoGetListResponse, error)
// rpc GetList (CarInfoGetListRequest) returns (stream CarInfo) {}
InsertList(context.Context, *CarInfoInsertListRequest) (*CarInfoInsertListResponse, error)
}
func RegisterCarInfoServiceServer(s *grpc.Server, srv CarInfoServiceServer) {
s.RegisterService(&_CarInfoService_serviceDesc, srv)
}
func _CarInfoService_GetList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CarInfoGetListRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CarInfoServiceServer).GetList(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/car_info.CarInfoService/GetList",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CarInfoServiceServer).GetList(ctx, req.(*CarInfoGetListRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CarInfoService_InsertList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CarInfoInsertListRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CarInfoServiceServer).InsertList(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/car_info.CarInfoService/InsertList",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CarInfoServiceServer).InsertList(ctx, req.(*CarInfoInsertListRequest))
}
return interceptor(ctx, in, info, handler)
}
var _CarInfoService_serviceDesc = grpc.ServiceDesc{
ServiceName: "car_info.CarInfoService",
HandlerType: (*CarInfoServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetList",
Handler: _CarInfoService_GetList_Handler,
},
{
MethodName: "InsertList",
Handler: _CarInfoService_InsertList_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "car_info.proto",
}
Entity 結構
type CarInfo struct {
CarOwner string
CarType string
DriveDate time.Time
Km string
Test string
}
取得清單方法
func (s *server) GetList(ctx context.Context, in *car_info.CarInfoGetListRequest) (*car_info.CarInfoGetListResponse, error) {
var list []CarInfo
car_list := []*car_info.CarInfo{}
engine.Limit(1000, 0).Find(&list)
orm, _ := json.Marshal(list)
json.Unmarshal(orm, &car_list)
return &car_info.CarInfoGetListResponse{Cars: car_list}, nil
}
批次新增
func (s *server) InsertList(ctx context.Context, in *car_info.CarInfoInsertListRequest) (*car_info.CarInfoInsertListResponse, error) {
var list []CarInfo
orm, _ := json.Marshal(in.Cars)
json.Unmarshal(orm, &list)
for _, car := range list {
engine.Insert(&car)
}
return &car_info.CarInfoInsertListResponse{Cars: in.Cars}, nil
}
Java Client Side
public class CarInfoClient {
private static final Logger logger = Logger.getLogger(CarInfoClient.class.getName());
private final ManagedChannel channel;
private final ServiceGrpc.ServiceBlockingStub blockingStub;
public CarInfoClient(String host, int port) {
this(ManagedChannelBuilder.forAddress(host, port)
.usePlaintext()
.build());
}
CarInfoClient(ManagedChannel channel) {
this.channel = channel;
blockingStub = ServiceGrpc.newBlockingStub(channel);
}
public void getList() {
CarInfoGetListRequest request = CarInfoGetListRequest.newBuilder().build();
CarInfoGetListResponse response;
try {
response = blockingStub.getList(request);
} catch (StatusRuntimeException e) {
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
return;
}
logger.info("CarList: " + response.getCarsList());
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
public static void main(String[] args) throws Exception {
CarInfoClient client = new CarInfoClient("localhost", 50051);
try {
client.getList();
} finally {
client.shutdown();
}
}
}
Golang Client Side
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
if err != nil {
log.Fatalf("連線失敗:_%v", err)
}
defer conn.Close()
car_service := car_info.NewCarInfoServiceClient(conn)
// insert
var list []*car_info.CarInfo
for i := 1; i <= 10; i++ {
list = append(list, &car_info.CarInfo{CarOwner: strconv.Itoa(counter) + ":" + strconv.Itoa(i), CarType: "n"})
}
car_service.InsertList(context.Background(), &car_info.CarInfoInsertListRequest{Cars: list})
}
This content originally appeared on DEV Community and was authored by DEV Community
DEV Community | Sciencx (2022-03-01T06:13:01+00:00) Java Spring VS Go gRPC. Retrieved from https://www.scien.cx/2022/03/01/java-spring-vs-go-grpc/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.