本文涉及的环境及测试工具
java8,netbean8,jersey2.5.1,tomcat8
WizTools3.5
注意:一定要用netbean管理的jersey库,从网上下的jar包不全,在测试json输出时会报异常
其它的jar
JAX-RS2.0,javax.json-1.0.1
至于cdi注入,因为jersey的库中使用的是hk2,可以使用
开始吧.
1.实体举例
User bean
public class User implements Serializable{
/** * ID */
private int qiuid;
/** * 用户名 */
private String name;
/** * 手机号 */
private String phone;
/** * 邮箱 */
private String mail;
/** * 密码 */
private String pswd;
/** * 注册日期 */
private Date regDate;
/** * 最后活跃日期 */
private Date activeDate;
/** * 注册IP */
private String regIP;
/** * 最后活跃IP */
private String activeIP;
/** * 因子 */
private String factor;
/** * 状态 */
private boolean status;
/** * 应用 */
private AppNode app;
/** * 银行卡 */
private List<BankCard> cards;
/** * 钱包 */
private Wallet wall;
//ETC GET/SET
}
BankCard bean
@XmlRootElement
public class BankCard implements Serializable{
/** * ID(银行卡编号) */
private int id=0;
/** * 银行名称 */
private String names;
/** * 银行帐号 */
private String account;
/** * 开户人 */
private String realname;
/** * 银行地址:南大街支行 */
private String address;
/** * 是否是默认的 */
private boolean isDefault=false;
/** * 是否可用 */
private boolean status=true;
/** * 关联的会员 */
private User user;
//ETC get/set
}
说明,因为bankcard可以输出为application/xml,所以需要加上jaxb的注解:@XmlRootElement
2.服务层,接口层面不需要特别的注解,下面是业务接口的实现
import javax.inject.Inject;
import net.iqido.dao.UserDao;
import net.iqido.entity.User;
import net.iqido.service.UserService;
/** * * @author Administrator */
public class UserServiceImple implements UserService {
@Inject
private UserDao userDao;
@Override
public int addUser(String username, String pswd, String phone, String mail) {
System.out.println("[SEL]name:"+username);
User u=new User();
u.setName(username);
u.setPhone(phone);
u.setPswd(pswd);
u.setMail(mail);
return userDao.addUser(u);
}
@Override
public boolean lockUser(int qiuid) {
return userDao.updateUserStatus(qiuid,false);
}
@Override
public boolean updateUser(int qiuid, String oldpswd, String newpswd) {
return userDao.updateUserPassword(qiuid, oldpswd, newpswd);
}
@Override
public void offLineUser(int qiuid) {
}
@Override
public int getUser(String username, String pswd) {
return userDao.getUserFromUserName(username, pswd).getQiuid();
}
@Override
public boolean checkPhone(String phone) {
return userDao.getUserFromPhone(phone)==null?false:true;
}
@Override
public boolean checkMail(String mail) {
return userDao.getUserFromMail(mail)==null?false:true;
}
@Override
public boolean checkUserName(String name) {
return userDao.getUserFromName(name)==null?false:true;
}
}
import javax.inject.Inject;
import net.iqido.dao.BankCardDao;
import net.iqido.entity.BankCard;
import net.iqido.service.BankCardService;
/** * * @author Administrator */
public class BankCardServiceImple implements BankCardService{
@Inject
private BankCardDao bankCardDao;
@Override
public int addCard(BankCard card, int qiuid) {
return bankCardDao.addBankCard(qiuid, card);
}
@Override
public int lockCard(int id, int qiuid) {
return bankCardDao.updateBankCardStatus(qiuid, id, false)?1:0;
}
@Override
public boolean updateCard(int id, int qiuid, String names, String account, String realname) {
BankCard b=new BankCard();
b.setId(id);
b.setNames(names);
b.setAccount(account);
b.setRealname(realname);
return bankCardDao.updateBankCard(qiuid, b);
}
@Override
public BankCard getCard(int qiuid) {
return bankCardDao.getBankCard(qiuid);
}
@Override
public boolean setDefaultCard(int id, int qiuid) {
return bankCardDao.updateBankCardIsDefault(qiuid, id, true);
}
}
说明,@Inject cdi注入注解,后面有一个hk2的配置类会告诉cdi去实例哪个实现类
3.dao层,接口照例没有需要的注解,接品实现我用的是jodd,这里没有什么特别要说的,官方给的说明很全面
4.hk2的配置类
import net.iqido.dao.*;
import net.iqido.dao.imple.*;
import net.iqido.service.*;
import net.iqido.service.imple.*;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
/** * CDI配置 * @author Administrator */
public class IqidoRestBuilder extends AbstractBinder{
@Override
protected void configure() {
//会员
bind(UserServiceImple.class).to(UserService.class);
bind(UserDaoImple.class).to(UserDao.class);
//银行卡
bind(BankCardServiceImple.class).to(BankCardService.class);
bind(BankCardDaoImple.class).to(BankCardDao.class);
}
说明,至所以我写成这样,其实也可以看出很容易把一个非服务的应用转成服务,当然是服务需要的注入
5.资源类(REST的重点部分)
import javax.annotation.ManagedBean;
import javax.inject.Inject;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PUT;
import net.iqido.entity.BankCard;
import net.iqido.resource.tools.AppNodeAuth;
import net.iqido.service.BankCardService;
/** * 银行卡服务 * * @author Administrator */
@ManagedBean
@Path("card")
@AppNodeAuth
public class CardResource {
@Inject
private BankCardService bankCardService;//=new BankCardServiceImple();
@Context
private UriInfo context;
/** * Creates a new instance of CardResource */
public CardResource() {
}
@POST
@Path("add/{id}")
@Produces("application/json")
@Consumes("application/x-www-form-urlencoded")
public BankCard add(
@FormParam("name")String name,
@FormParam("account")String account,
@FormParam("real")String real,
@FormParam("address")String address,
@PathParam("id")int qiuid){
BankCard bc=new BankCard();
bc.setAccount(account);
bc.setNames(name);
bc.setRealname(real);
bc.setAddress(address);
bc.setId(bankCardService.addCard(bc, qiuid));
return bc;
}
@DELETE
@Path("lock/{id}/{record}")
public int lock(
@PathParam("id")int qiuid,
@PathParam("record")int id){
return bankCardService.lockCard(id, qiuid);
}
@PUT
@Path("update/{id}/{record}")
@Consumes("application/json")
public boolean update(
@PathParam("id")int qiuid,
@PathParam("record")int id,
BankCard card){
return bankCardService.updateCard(id, qiuid, card.getNames(), card.getAccount(), card.getRealname());
}
@GET
@Path("get/{id}")
@Produces("application/json")
public BankCard get(@PathParam("id")int qiuid){
return bankCardService.getCard(qiuid);
}
@PUT
@Path("setting/{id}/{record}")
@Consumes("application/json")
public boolean setting(@PathParam("id")int qiuid,@PathParam("record")int id){
return bankCardService.setDefaultCard(id, qiuid);
}
}
import javax.annotation.ManagedBean;
import javax.inject.Inject;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.PathParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Request;
import net.iqido.resource.tools.AppNodeAuth;
import net.iqido.service.UserService;
/** * 会员服务 * * @author Administrator */
@ManagedBean
@Path("user")
@AppNodeAuth
public class UserResource {
@Inject
private UserService userService;
@Context
private UriInfo context;
@Context
private Request request;
public UserResource() {
}
@POST
@Path("register")
@Consumes("application/x-www-form-urlencoded")
public int add(
@FormParam("name")String username,
@FormParam("pswd")String pswd,
@FormParam("phone")String phone,
@FormParam("mail")String mail) {
return userService.addUser(username, pswd, phone, mail);
}
@POST
@Path("login")
@Consumes("application/x-www-form-urlencoded")
public int get(
@FormParam("name")String username,
@FormParam("pswd")String userpswd) {
//是否有必要返回一个预定的格式:{id:x,app:x,name:,phone:,mail:x,domain:}
//或者直接由服务写入到cookie中
return userService.getUser(username, userpswd);
}
@POST
@Path("reset/{id}")
@Consumes("application/x-www-form-urlencoded")
public boolean update(
@PathParam("id")int qiuid,
@FormParam("old")String oldpswd,
@FormParam("used")String newpswd){
return userService.updateUser(qiuid, oldpswd, newpswd);
}
@GET
@Path("logout/{id}")
public String offline(@PathParam("id")int qiuid){
userService.offLineUser(qiuid);
return "OK";
}
@DELETE
@Path("lock/{id}")
public boolean lock(@PathParam("id")int qiuid){
return userService.lockUser(qiuid);
}
@GET
@Path("check")
public boolean checkUsername(@QueryParam("value")String option,@QueryParam("category")int cate){
boolean redate;
switch(cate){
case 1:
redate=userService.checkPhone(option);
break;
case 2:
redate=userService.checkUserName(option);
break;
case 3:
redate=userService.checkMail(option);
break;
default:
redate=true;
}
return redate;
}
}
说明
@Path 指明资源的路径,和下面的入口一起组合而成app/类的path/方法的path,@Path(“add/{id}”)中的{id}是路径参数,可以在方法参数(@PathParam(“id”)int uid),注意引号中的一定要对应路径占位字符,参数类型后面的可以不同
@GET, @PUT, @POST, @DELETE 和 @HEAD 是http协议中的请求方法
@Consumes 指定方法可以使用的请求正文体的mime-type类型,我使用的有:
POST对应的是@Consumes(“application/x-www-form-urlencoded”),这时方法的参数中使用@FormParam
PUT对应的是@Consumes({“application/json”,”application/xml”})
DELETE,GET 都是通过路径参数
@Produces 指定响应内容的mime-type类型,我觉得最后不好一个方法用xml,一个方法用json,最好统一,便于客户端程序处理,当然这个可以通过响应的内容类型(content-type),当然免不了使用if或者方法委托
其它
可以在方法参数中使用一些请求的头部内容@HeaderParam,请求中的cookie内容@CookieParam,或者path后面的查询字符串(query string)@QueryParam
在类中可以使用@Context获取上下文中的一些信息,例如javax.ws.rs.core.UriInfo,javax.ws.rs.core.Request
像你看到的如果要向客户端响应json/xml,不需要作特别的转换,方法直接输出bean实例
6.入口servlet
import javax.ws.rs.ApplicationPath;
import net.iqido.resource.rest.IqidoRestBuilder;
import net.iqido.resource.tools.ApplicationCloudListener;
import org.glassfish.jersey.server.ResourceConfig;
/** * 入口点 * @author Administrator */
@ApplicationPath("app")
public class RestServiceApplication extends ResourceConfig{
public RestServiceApplication(){
//扫描包
packages("net.iqido.resource.rest");
packages("net.iqido.resource.tools");
//HK2 CDI
register(new IqidoRestBuilder());
register(ApplicationCloudListener.class);
}
}
7.web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<servlet>
<servlet-name>RESTFulApp</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>net.iqido.web.RestServiceApplication</param-value>
</init-param>
<init-param>
<param-name>javax.json.stream.JsonGenerator.prettyPrinting</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>RESTFulApp</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>