未标准化进行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层如何注入的问题就完美解决了,带大家看下上述注册接口实现的效果