未标准化进行java开发时,没有进行对业务代码以及公用逻辑进行分离,如果需求遇到改动,需要改公用逻辑时,需要去一处处业务代码中去找,大大的浪费了时间,使用接口后,可以合理的解决这一问题。
public interface UserService {
// 新用户注册接口
public Integer AddUser(String userName,String userId,String password,String avatarSrc,String createTime);
}
复制代码
// 实现注册接口
@Override
public Integer AddUser(String userName, String userId, String password, String avatarSrc, String createTime) {
User row = new User();
row.setUserName(userName);
row.setUserId(userId);
row.setPassword(password);
row.setAvatarSrc(avatarSrc);
row.setCreateTime(createTime);
// 增加用户,向数据库插入一条数据
return userMapper.insertUser(row);
}
复制代码
至此就就完成了一个接口的声明到实现
我们先来看看不使用接口时,将功能的实现和业务代码全写在 controller 层的代码,这里我们以登录为例,如果遇到新的需求,我们就要去找找功能实现部分进行修改,业务代码过多时是一件很头疼的事情
@RestController
@RequestMapping("/user")
public class GreetingController {
private final Logger logger= LoggerFactory.getLogger(getClass());
@Resource
private UserInfoMapper userMapper;
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@CrossOrigin()
// 登录请求
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(@RequestBody String request){
// 获取前端参数
JSONObject jsReq = new JSONObject(request);
JSONObject jsReply = new JSONObject();
String username = jsReq.getString("username");
String password = jsReq.getString("password");
UserInfo row = new UserInfo();
JSONArray queryType = new JSONArray();
queryType.put("name");
queryType.put("password");
queryType.put("career");
queryType.put("avatarSrc");
queryType.put("userID");
row.setQueryType(queryType);
row.setName(username);
List<UserInfo> resultList = userMapper.customQuery(row);
JSONArray result = null;
if(resultList.size()>0){
result = new JSONArray(resultList);
if(password.equals(result.getJSONObject(0).getString("password"))){
jsReply.put("code",0);
// 根据当前用户名和密码生成token
jsReply.put("token", JwtUtil.sign(username,password));
jsReply.put("msg","验证成功,token有效期为30分钟");
jsReply.put("avatarSrc",result.getJSONObject(0).getString("avatarSrc"));
jsReply.put("userID",result.getJSONObject(0).getString("userID"));
}else{
jsReply.put("code",-2);
jsReply.put("msg","密码错误");
}
}else{
jsReply.put("code",-1);
jsReply.put("msg","当前登录用户不存在");
}
return jsReply.toString();
}
}
复制代码
// service层
package com.lk.service;
public interface UserService {
// 新用户注册接口
public Integer AddUser(String userName,String userId,String password,String avatarSrc,String createTime) throws Exception;
}
复制代码
// serviceimpl层(接口实现)
package com.lk.serviceimpl;
import com.lk.dao.UserMapper;
import com.lk.entity.User;
import com.lk.service.UserService;
import com.lk.utils.HMacMD5;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
private final Logger logger= LoggerFactory.getLogger(getClass());
// 从配置文件读取加密key
@Value("${HMacKey}")
private String HMacKey;
// 实现注册接口
@Override
public Integer AddUser(String userName, String userId, String password, String avatarSrc, String createTime) throws Exception {
// 判断参数是否合法
if(userName.equals("")||userName.length()>10){
logger.error("违规操作:用户名为空或用户名长度大于10,"+userName);
return -1;
}else if(password.equals("")||password.length()>16){
logger.error("违规操作:密码为空或密码长度大于10,"+password);
return -2;
}else if(avatarSrc.equals("")||avatarSrc.length()>300){
logger.error("违规操作:头像地址为空或头像地址过长,"+avatarSrc);
return -3;
}
// 对密码进行加密
password = HMacMD5.encryptHMAC2String(password,HMacKey);
User row = new User();
row.setUserName(userName);
row.setUserId(userId);
row.setPassword(password);
row.setAvatarSrc(avatarSrc);
row.setCreateTime(createTime);
logger.info(userMapper+"");
// 增加用户,向数据库插入一条数据
int result = userMapper.insertUser(row);
logger.info(result+"");
return result;
}
}
复制代码
// controller层(业务代码)
package com.lk.controller;
import com.lk.dao.UserMapper;
import com.lk.serviceimpl.UserServiceImpl;
import com.lk.utils.DateUtil;
import com.lk.utils.UUIDUtil;
import com.lk.utils.UnifiedReturnDataUtil;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/api/user")
public class UserController {
@Resource
private UserMapper userMapper;
@Resource(name = "userServiceImpl")
private UserServiceImpl userService;
private final Logger logger= LoggerFactory.getLogger(getClass());
@RequestMapping(value = "/registered", method = RequestMethod.POST)
public String login(@RequestBody String request) throws Exception {
// 生成userId
String userId = UUIDUtil.getUUID();
// 生成注册日期
String createTime = DateUtil.getThisTime();
// 序列化前端参数
JSONObject jsReq = new JSONObject(request);
// 实例化注册服务
// UserServiceImpl userService = new UserServiceImpl();
// 调用注册接口
int result = userService.AddUser(jsReq.getString("userName"),userId,jsReq.getString("password"),jsReq.getString("avatarSrc"),createTime);
JSONArray responseData = new JSONArray();
// 判断是否注册成功
if(result>0){
return UnifiedReturnDataUtil.returnJSONString(result,"注册成功",responseData);
}
return UnifiedReturnDataUtil.returnJSONString(result,"注册失败",responseData);
}
}
复制代码
在controller层使用接口实现类里的方法时,spring注解的内容一直为null,无法拿到@Resource注解的mybatis里的mapper对象和@Value注解的获取yml文件中的属性,接口实现类报空指针异常。 原因是:我在controller层实例化接口实现类时,对象是自己new的,没有走spring,所以一直为null。找了很多解决方案,走了很多弯路,最终使用@Service注解和@Resource注解完美解决了这个问题。 我的问题可以描述为:接口的实现类在controller层如何注入
// 错误的解决方案,实现类不走spring容器,报空指针异常 UserServiceImpl userService = new UserServiceImpl(); 复制代码
// 这里括号中的名字为当前类名首字母小写
@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
/////++++++++++++++++++++++++/////
}
复制代码
// controller层
public class UserController {
// 括号里的name值对应接口实现类@Service注解括号里的名字
@Resource(name = "userServiceImpl")
private UserServiceImpl userService;
}
复制代码
至此,关于接口实现类在controller层如何注入的问题就完美解决了,带大家看下上述注册接口实现的效果