项目总结:
这是我的第一个SSM项目 也是我第一次系统的接触一个完整的框架,本项目分为前台和后台系统,分别是用户界面和管理员界面。主要技术为:Spring,Springmvc,mybatis,并且在前台的数据缓存中用到了基于No-sql技术的Redis。
我对这些技术的理解:
Spring:Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建,是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。
Spring 的主要核心点:
- 控制反转:Spring通过一种称作控制反转(IOC)的技术促进了低耦合。当应用了IOC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IOC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
- 面向切面:Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。简单的来说就是各个模块不会互相干扰,这就像我们的并联电路一样,一个模块停止工作不会影响到其他模块。这也满足了我们的编程思想:高内聚,低耦合。
- 容器:Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
- MVC:Spring的作用是整合,但不仅仅限于整合,Spring 框架可以被看做是一个企业解决方案级别的框架。客户端发送请求,服务器控制器(由DispatcherServlet实现的)完成请求的转发,控制器调用一个用于映射的类HandlerMapping,该类用于将请求映射到对应的处理器来处理请求。HandlerMapping 将请求映射到对应的处理器Controller(相当于Action)在Spring 当中如果写一些处理器组件,一般实现Controller 接口,在Controller 中就可以调用一些Service 或DAO 来进行数据操作 ModelAndView 用于存放从DAO 中取出的数据,还可以存放响应视图的一些数据。 如果想将处理结果返回给用户,那么在Spring 框架中还提供一个视图组件ViewResolver,该组件根据Controller 返回的标示,找到对应的视图,将响应response 返回给用户。
Spring的优势:
1.低侵入式设计,代码污染极低
2.独立于各种应用服务器,基于Spring框架的应用,可以真正实现Write Once,Run Anywhere的承诺
3.Spring的DI机制降低了业务对象替换的复杂性,提高了组件之间的解耦
4.Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用
5.Spring的ORM和DAO提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问
6.Spring并不强制应用完全依赖于Spring,开发者可自由选用Spring框架的部分或全部
Mybatis:
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
在使用Mybatis时,我使用了代码自动生成器 Generator,它可以根据数据库对象来自动生成实体类Model和映射Mapper。它提供了标准的增删改查功能,极大的增加了我的工作效率。
Mybatis的优势:
- MyBatis 最强大的特性之一就是它的动态语句功能,把SQL语句条件连接在一起是一件非常痛苦的事,而Mybatis的动态SQL语句解决了这个问题
- Generator文件:可以自动生成我的Model和Mapper类。
Spring和Mybatis的集成
这是本次项目的一个重要核心点,单独使用Mybatis 是有很多限制的(比如无法实现跨越多个session的事务),而且很多业务系统本来就是使用spring来管理的事务,因此Mybatis 最好与spring集成起来使用。
<!--让spring生成mapper接口的代理实现类-->
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--对哪些包下的类生成mapper代理类-->
<property name="basePackage" value="com.imcode.mall.mapper"/>
</bean>
<!--配置事务管理器-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 事务增强/通知 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 切面配置 -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.imcode.common.service.*Service.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.imcode.mall.service.*Service.*(..))"/>
</aop:config>
Redis:
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
Redis 主要用在前台数据的操作,他使得用户在对我们的网站进行浏览时不需要频繁的访问数据库,从而大大的提高了数据传输的效率
以下是我的项目的前后台页面:
前台首页:
商品详情页:
购物车:
最近浏览:
最近浏览我用到了Redis技术,在用户访问商品详情时,记录下当前的商品ID:
@GetMapping("/detail/{id}")
public String detail (@PathVariable Integer id, Model model){
Goods goods = goodsService.getById(id);//根据商品ID查找商品详情
Member member=(Member)session.getAttribute("sessionUser");//获取当前登录的用户
redisTemplate.opsForHash().put(prefix+goods.getId()+memberId,"record",goods);//把用户浏览的商品加到Redis中
redisTemplate.expire(prefix+goods.getId()+memberId,5,TimeUnit.MINUTES);//设置Redis的有效生命周期为5分钟
model.addAttribute("goods",goods);
return "goods/goods_detail";
}
商品支付页面:
在提交订单时,应该把当前购物车中的商品删除:
编辑收货地址:
在收货地址这个模块,我在AddressMapper 写了三个方法:
//查询默认地址
<select id="findDefault" resultMap="BaseResultMap">
select * from mall_address where member_id=#{id} and is_default=0
</select>
//查询非默认地址
<select id="findUnDefaultList" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select * from mall_address where member_id=#{id} and is_default!=0
</select>
//根据当前用户ID查询所有收货地址
<select id="getAllById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select * from mall_address where member_id = #{id}
</select>
在上面的界面中 我写了一个 设为默认的功能。点击可把需要的地址设置成默认地址:具体代码实现:
Controller层:
@GetMapping("/address")
public String address(Model model){
Address address = new Address();
address.setMemberId(getMemberId());
List<Address>list=addressService.findList(address);
model.addAttribute("defaultAddress",addressService.findDefault());
model.addAttribute("addressList",list);
return "member/member_address";
}
@GetMapping("/address1")
public String set(@RequestParam Integer addressId){
Address address=addressService.getById(addressId);
address.setIsDefault(0);
addressService.update(address);
List<Address>list=addressService.findAllById();
for (Address address1:list){
if (address1.getId()!=addressId){
address1.setIsDefault(1);
addressService.update(address1);
}
}
return "redirect:/member/address";
}
Service层:
public Address findDefault(){
Member member= (Member) session.getAttribute("sessionUser");
Address address=addressMapper.findDefault(member.getId());
return address;
}
@Override
public List<Address> findList(Address param) {
Member member= (Member) session.getAttribute("sessionUser");
return addressMapper.findUnDefaultList(member.getId());
}
public List<Address>findAllById(){
Member member= (Member) session.getAttribute("sessionUser");
List<Address>list=addressMapper.getAllById(member.getId());
return list;
}
本项目接入了支付宝的沙箱环境API,模拟了用户支付系统:
后台系统:
我觉得没什么东西,不写了。