摘要:
面向接口编程这几个字,听起来真的很熟悉。但是之前体会不是很深,基本上都停留在很低层面上的应用!下面以代码说明:
1 package cn.ilxy.service.product; 2 3 import java.util.List; 4 5 import cn.ilxy.bean.product.Brand; 6 import cn.ilxy.enity.Pagination; 7 import cn.ilxy.query.BrandQuery; 8 9 /** 10 * 品牌 11 * @author: 张荣 12 * @date: 2016年3月22日 13 */ 14 public interface BrandService { 15 //得到品牌分页的相关参数 16 public Pagination getBrandListWithPage(Brand brand); 17 //List集合:查询品牌分页 18 public List<Brand> getBrandList(BrandQuery brandQuery); 19 }
1 package cn.ilxy.service.product; 2 3 import java.util.List; 4 5 import javax.annotation.Resource; 6 7 import org.springframework.stereotype.Service; 8 import org.springframework.transaction.annotation.Transactional; 9 10 import cn.ilxy.bean.product.Brand; 11 import cn.ilxy.dao.product.BrandDao; 12 import cn.ilxy.enity.Pagination; 13 import cn.ilxy.query.BrandQuery; 14 15 /** 16 * 品牌事务 17 * @author: 张荣 18 * @date: 2016年3月21日 19 */ 20 @Service 21 @Transactional 22 public class BrandServiceImpl implements BrandService { 23 @Resource 24 private BrandDao brandDao; 25 26 @Override 27 @Transactional(readOnly = true) 28 public Pagination getBrandListWithPage(Brand brand) { 29 /*1、起始页号:从1开始索引,则startRow = (pageNo - 1)* pageSize 30 * 2、每页显示记录数 31 * 3、总的记录条数 32 */ 33 Pagination pagination = new Pagination(brand.getPageNo(), brand.getPageSize() , brandDao.getBrandCount(brand)); 34 //Brand集合 35 pagination.setList(brandDao.getBrandListWithPage(brand)); 36 return pagination; 37 } 38 39 @Override 40 public void addBrand(Brand brand) { 41 brandDao.addBrand(brand); 42 } 43 44 }
最后在Controller层中注入,并最终完成使用!自己在之前的编码过程中就一直停留在这个层面上!的确没有体会到面向接口编程的精髓,更准确的说,自己对向上转型算是有一定的理解。就像定义泛型一样:List<String> lst = new ArrayList<String>();
而今天自己看到了一个新的情景下的使用,才对面向接口编程思想有更深的体会和认识!
情景:
在做网站时,肯定涉及到Session,比如说从Session域中取值,将值存到Session域中······最好肯定是将这些方法抽象成一个类了。在网站的开发阶段,都是在本机上做测试。这时使用的就是本地Session了,等到项目发布后,使用的肯定就不是本地Session,而是远程Session了。那么问题来了,该怎么设计,才能在项目发布时尽量减少对项目源码的修改?
分析:
这两种情况下的Session类中的方法签名肯定是完全一样的了,只是里面的实现细节不一样而已。而这种特点就非常符合接口的使用场景了。本身从接口的定义上来说,接口就是一组方法的抽象。
源码:
分析清楚后,代码如下:
1 package cn.ilxy.web.session; 2 3 import java.io.Serializable; 4 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 8 /** 9 * 本地session 10 * @author: 张荣 11 * @date: 2016年3月30日 12 */ 13 public interface SessionProvider { 14 /** 15 * 往Session里设置值 16 */ 17 public void setAttribute(HttpServletRequest request , HttpServletResponse response , String name , Serializable value ); 18 19 /** 20 * 从Session中取值 21 */ 22 public Serializable getAttibute(HttpServletRequest request , HttpServletResponse response ,String name); 23 24 /** 25 * 退出登录 26 */ 27 public void loginOut(HttpServletRequest request , HttpServletResponse response ); 28 29 /** 30 * 获取SessionID 31 */ 32 public String getSessionId(HttpServletRequest request , HttpServletResponse response); 33 }
1 package cn.ilxy.web.session; 2 3 import java.io.Serializable; 4 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 import javax.servlet.http.HttpSession; 8 9 /** 10 * 本地Session 11 * @author: 张荣 12 * @date: 2016年3月30日 13 */ 14 public class HttpSessionProvider implements SessionProvider{ 15 16 @Override 17 public void setAttribute(HttpServletRequest request, HttpServletResponse response , String name, Serializable value) { 18 HttpSession session = request.getSession(); //true如果有返回Session,没有就创建一个Cookie JSESSIONID 19 session.setAttribute(name, value); 20 } 21 22 @Override 23 public Serializable getAttibute(HttpServletRequest request, HttpServletResponse response ,String name) { 24 HttpSession session = request.getSession(false); 25 if (session != null) { 26 return (Serializable) session.getAttribute(name); 27 } 28 return null; 29 } 30 31 @Override 32 public void loginOut(HttpServletRequest request , HttpServletResponse response) { 33 HttpSession session = request.getSession(false); 34 if (session != null) { 35 session.invalidate(); 36 } 37 //Cookie: JSESSION 38 39 } 40 41 @Override 42 public String getSessionId(HttpServletRequest request , HttpServletResponse response) { 43 // request.getRequestedSessionId(); //http://localhost:8080/html/sstf.shtml?JESSIONID=ewerq235:获取的是URL的SESSIONID 44 return request.getSession().getId(); 45 } 46 47 }
1 package cn.ilxy.web.session; 2 3 import java.io.Serializable; 4 import java.util.HashMap; 5 import java.util.Map; 6 import java.util.UUID; 7 8 import javax.annotation.Resource; 9 import javax.servlet.http.Cookie; 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletResponse; 12 13 import com.danga.MemCached.MemCachedClient; 14 15 /** 16 * 远程Session,存放在Memcached缓存服务器中 17 * @author: 张荣 18 * @date: 2016年4月3日 19 */ 20 public class CacheSessionProvider implements SessionProvider{ 21 22 @Resource 23 private MemCachedClient memCachedClient; 24 25 private int expiry = 60 * 30; 26 27 private static final String JSESSIONID="JSESSIONID"; 28 29 public void setExpiry(int expiry) { 30 this.expiry = expiry; 31 } 32 33 @Override 34 public void setAttribute(HttpServletRequest request, HttpServletResponse response , String name, Serializable value) { 35 Map<String, Serializable> session = new HashMap<String , Serializable>(); 36 session.put(name, value); 37 memCachedClient.set(getSessionId(request , response), session , expiry); 38 } 39 40 @Override 41 public Serializable getAttibute(HttpServletRequest request, HttpServletResponse response , String name) { 42 @SuppressWarnings("unchecked") 43 Map<String, Serializable> session = (Map<String, Serializable>) memCachedClient.get(getSessionId(request, response)); 44 if (session != null) { 45 return session.get(name); 46 } 47 return null; 48 } 49 50 @Override 51 public void loginOut(HttpServletRequest request , HttpServletResponse response) { 52 if (memCachedClient.keyExists(getSessionId(request, response))) { 53 memCachedClient.delete(getSessionId(request, response)); 54 /* 55 删除Cookie中的SessionID 56 Cookie cookie = null; 57 Cookie[] cookies = request.getCookies(); 58 for(Cookie c: cookies){ 59 if (c.getName().equals(getSessionId(request, response))) { 60 cookie = c; 61 break; 62 } 63 } 64 if (cookie != null) { 65 cookie.setMaxAge(0); 66 cookie.setPath("/"); 67 }*/ 68 } 69 } 70 71 @Override 72 public String getSessionId(HttpServletRequest request , HttpServletResponse response) { 73 Cookie[] cookies = request.getCookies(); 74 if (cookies != null && cookies.length > 0) { 75 for(Cookie cookie : cookies){ 76 if (JSESSIONID.equals(cookie.getName())) { 77 return cookie.getValue(); 78 } 79 } 80 } 81 82 String sessionId = UUID.randomUUID().toString().replaceAll("-", ""); 83 Cookie c = new Cookie(JSESSIONID, sessionId); 84 c.setDomain("/"); 85 c.setMaxAge(-1); 86 response.addCookie(c); 87 88 return sessionId; 89 } 90 91 }
加载Bean的Spring文件:

在项目的发布阶段,只需要将上图中class路径写成分布式缓存Session的包+类的路径就可以。而无须再对Java代码人任何修改!而开发人员还认为在服务器上运行的是本地Session实现类中的代码!
总结:
面向接口的编程思想的精髓就是一组方法的抽象!通过接口,就可以实现面向对象编程思想的多态特性。就像是USB接口,只要是满足USB接口的标准规格,就可以实现即插即用,无须关心USB接口中的具体实现,也实现了面向对象思想的封装特性。而在本例中,更是明显的体现了这一点,对注入的Session接口而言,完全隐藏了分布式缓存Session的实现细节,或者是分布式缓存Session实现类是透明的!更是结合Spring的IOC容器瞒天过海,实现了“偷天换日”!
面向接口编程是面向对象编程的升华,巧妙体现了编程之美!
浙公网安备 33010602011771号