上一篇博客中已经简单的整理了移动端调用PC端接口的实现流程,这其中涉及到springMVC拦截器的使用。下面通代码对应上篇博客中的流程简介看一下具体是如何实现的。首先定义一个拦截器,需要实现HandlerInterceptor接口,这个接口有三个方法,在这里的作用是验证用户是否登录,所用只用preHandle这个方法就可以完成。首先需要建立两个类,InDto和OutDto分别是信息接收实体和信息反馈实体。
InDto:主要是用来接收移动端URL请求的参数包括请求的controller、方法、参数。
- <span style="font-size:18px;">/**
- * <p>Title:InDto</p>
- * Description:参数接收实体类
- */
- public class InDto {
- /**
- * 版本号
- *一般为固定的,主要是为了和Action进行凭借识别对应的controller
- */
- private String version;
- /**
- * 方法包名
- */
- private String action;
- /**
- * 方法名
- */
- private String method;
- /**
- * 时间戳
- */
- private String timeStamp;
- /**
- * 请求参数
- */
- private String req;
- /**
- * 接口请求request
- */
- private HttpServletRequest request;
- /**
- * 接口请求response
- */
- private HttpServletResponse response;
- /**
- * 注入
- */
- private Object dao;
- public String getVersion() {
- return version;
- }
- public void setVersion(String version) {
- this.version = version;
- }
- public String getAction() {
- return action;
- }
- public void setAction(String action) {
- this.action = action;
- }
- public String getMethod() {
- return method;
- }
- public void setMethod(String method) {
- this.method = method;
- }
- public String getTimeStamp() {
- return timeStamp;
- }
- public void setTimeStamp(String timeStamp) {
- this.timeStamp = timeStamp;
- }
- public String getReq() {
- return req;
- }
- public void setReq(String req) {
- this.req = req;
- }
- public Object getDao() {
- return dao;
- }
- public void setDao(Object dao) {
- this.dao = dao;
- }
- public HttpServletRequest getRequest() {
- return request;
- }
- public void setRequest(HttpServletRequest request) {
- this.request = request;
- }
- public HttpServletResponse getResponse() {
- return response;
- }
- public void setResponse(HttpServletResponse response) {
- this.response = response;
- }
- //构造函数
- public InDto(Map<String,String[]> map) throws IOException{
- this.version=map.get("Version")!=null?map.get("Version")[0]:"";
- this.action=map.get("Action")!=null?map.get("Action")[0]:"";
- this.method=map.get("Method")!=null?map.get("Method")[0]:"";
- this.timeStamp=map.get("TimeStamp")!=null?map.get("TimeStamp")[0]:"";
- this.req=map.get("Req")!=null?map.get("Req")[0]:"";
- }
- }
- </span>
OutDto:主要用来返回约定的编码,方便移动端确定请求成功、失败、或者服务器请求失败。
- <span style="font-size:18px;">/**
- * <p>Title:OutDto</p>
- * Description: 信息反馈实体类
- */
- public class OutDto {
- /**
- * 成功
- */
- public static final String STATUS_SUCCESS="100";
- /**
- * 失败
- */
- public static final String STATUS_FAIL="200";
- /**
- * 服务端异常
- */
- public static final String STATUS_EXCEPTION="300";
- /**
- * 代码标识
- */
- private String status;
- /**
- * 信息
- */
- private String msg;
- /**
- * 返回数据
- */
- private Object data;
- public String getStatus() {
- return status;
- }
- public void setStatus(String status) {
- this.status = status;
- }
- public String getMsg() {
- return msg;
- }
- public void setMsg(String msg) {
- this.msg = msg;
- }
- public Object getData() {
- return data;
- }
- public void setData(Object data) {
- this.data = data;
- }
- /**
- * @描述 设置失败状态
- */
- public void setStatusFail() {
- this.status = STATUS_FAIL;
- }
- /**
- * @描述 设置失败状态和消息
- */
- public void setStatusFail(String msg) {
- this.status = STATUS_FAIL;
- this.msg=msg;
- }
- /**
- * @描述 设置成功状态
- */
- public void setStatusSuccess() {
- this.status = STATUS_SUCCESS;
- }
- /**
- * @描述 设置成功状态并插入data数据
- * @author quzf
- */
- public void setStatusSuccess(Object data,String msg) {
- this.status = STATUS_SUCCESS;
- this.data=data;
- this.msg=msg;
- }
- /**
- * @描述 设置成功状态并插入data数据
- */
- public void setStatusSuccess(String msg) {
- this.status = STATUS_SUCCESS;
- this.msg=msg;
- this.data="";
- }
- }
- </span>
移动端约定的请求接口的URL:
- http://localhost:8080/test/Service/dataSync.do?&Version=1.0&Action=login&Method=Login &TimeStamp=10000&Req={"params":{
- "userName": "admin",
- "userPwd ": "123456"
- }
- }
编写一个拦截器实现接口HandlerInterceptor
- <span style="font-size:18px;">/**
- *
- *拦截器
- */
- public class DataSyncInterceptor implements HandlerInterceptor {
- @Autowired
- private OrganService organService;
- /**
- * @描述 验证用户名密码是否正确
- */
- public OutDto testLegal(HttpServletRequest request) throws Exception {
- //实例化一个InDto,同时获得了客户端传来的信息
- InDto inDto=new InDto(request.getParameterMap());
- JSONObject reqJSON = JSON.parseObject(inDto.getReq());
- String action = inDto.getAction();//获取到请求的Action
- OutDto outDto=new OutDto();
- if(action.equals("login")){//如果是登录进行验证
- String userName = reqJSON.getString("userName");
- String userPwd = reqJSON.getString("userPwd");
- User user = organService.login(userName, userPwd);
- if(user==null){
- outDto.setStatusFail();
- outDto.setMsg("用户名或密码不正确!");
- }else{
- outDto.setStatusSuccess();
- }
- return outDto;
- }
- }
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
- Object o) throws Exception {
- //请求参数注入InDto
- OutDto outDto=new OutDto();
- try {
- InDto inDto=new InDto(request.getParameterMap());
- //设置验证结果,先不走验证非法,直接返回成功
- outDto = testLegal(request);
- //参数验证结果成功后,执行下面的拦截器
- if(OutDto.STATUS_SUCCESS.equals(outDto.getStatus())){
- return true;
- }else{
- response.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.print(JsonUtil.object2json(outDto));
- out.close();
- return false;
- }
- } catch (Exception e) {
- response.setCharacterEncoding("UTF-8");
- outDto.setStatus(OutDto.STATUS_EXCEPTION);//异常时
- PrintWriter out = response.getWriter();
- out.print(JsonUtil.object2json(outDto));
- e.printStackTrace();
- out.close();
- return false;
- }
- }
- @Override
- public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
- Object arg2, ModelAndView arg3) throws Exception {
- // TODO Auto-generated method stub
- }
- @Override
- public void afterCompletion(HttpServletRequest arg0,
- HttpServletResponse arg1, Object arg2, Exception arg3)
- throws Exception {
- // TODO Auto-generated method stub
- }
- }
- </span>
拦截器配置到mvc的配置文件中:
- <mvc:interceptors>
- <mvc:interceptor>
- <!-- //映射路径后缀名 -->
- <mvc:mapping path="/Service/*"/>
- <!--//自定义拦截器 -->
- <bean class="interceptor.DataSyncInterceptor"/>
- </mvc:interceptor>
- </mvc:interceptors>
拦截器走完如果用户验证通过后preHandle方法返回true,由于没有配置其他的拦截器就会根据请求的URL开始调用对应的controller。请求的URL中有“http://localhost:1080/test/Service/dataSync.do” 所以会根据URL找到Service这个controller中的dataSync方法。
- <span style="font-size:18px;">/**
- * <p>Title:ServiceController</p>
- * Description: 移动端接口入口
- */
- @Controller
- @RequestMapping("Service")
- public class ServiceController{
- @RequestMapping({"/dataSync"})
- @ResponseBody
- public void dataSync(HttpServletRequest request, HttpServletResponse response) {
- OutDto outDto = new OutDto();
- try {
- InDto inDto=new InDto(request.getParameterMap());
- inDto.setRequest(request);
- inDto.setResponse(response);
- String method = inDto.getMethod();
- if(StringUtils.isBlank(method)){
- method=AtcConstant.getAtcClassMethod();
- }
- //依据action和method,然后读取配置中的类反射执行该class
- Object bean = SpringHelper.getBean(inDto.getAction()+inDto.getVersion());
- outDto=(OutDto) ReflectUtil.invoke(bean,method, inDto,outDto);
- } catch (Exception e) {
- outDto.setStatus(OutDto.STATUS_EXCEPTION);
- e.printStackTrace();
- }
- try {
- //返回的结构为字节流是调用,为移动端做附件下载时使用
- if ("返回流".equals(outDto.getMsg())) {
- OutputStream outputStream=response.getOutputStream();
- InputStream is=new FileInputStream(outDto.getData().toString());
- byte b[] = new byte[1024];
- int len = -1;
- while ((len = is.read(b)) != -1)
- outputStream.write(b, 0, len);
- is.close();
- outputStream.close();
- }else { //非字节流结果返回时调用
- response.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.print(JsonUtil.object2json(outDto));
- out.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- </span>
这个方法中的核心代码是:
String method = inDto.getMethod();
Object bean =SpringHelper.getBean(inDto.getAction()+inDto.getVersion());
outDto=(OutDto)ReflectUtil.invoke(bean,method, inDto,outDto);
根据请求的Action+Version 可以确定要调用的Controller,用ReflectUtil中的invoke方法,将得到的实体bean和要调用的方法名称作为参数传递就可以调用相应controller中的方法。以这次的登录为例Action=login;Version =1.0就会请求名为login1.0的Controller中的Login方法。在这个controller的方法中就可以写系统的业务逻辑代码。
小结:
移动端调用接口的代码实现就是这样的,通过拦截器进行登录验证,使用invoke调用请求的controller中的方法。