最近再弄一个关于网上商城的设计,使用的SSH(Spring SpringMVC 和 Mybatis)。出了一个问题,算是自己弄了差不多一天,想记下来以便提醒自己。

    在说问题之前先说说自己有关设计的东西。对于一个网上商城是有很多的商品分类的,就好像淘宝京东左边的那个菜单栏一样的分类,对于这个分类的处理可以使用静态的标签元素,但为了设计日后的扩展性我还是想做成动态的(就是在启动服务器的时候从数据库中读取商品分类表中的分类,将这些分类的信息封装在ApplicationContext中,再用JSTL在jsp页面进行显示,建议在建立一个Session的时候做这项工作,但因为我只是针对这一个项目,就没有考虑这么多了)。不知道这个能不能说明白,先贴几张图吧。

表titemtype

wKiom1OBTDehmB6xAAIej-FBn6U409.jpg

表的设计是不怎么规范,由于考虑了其他方面的原因,如果要按照数据设计的三范式来说,好吧,这个是个败笔。

wKioL1OBUO7DJ77mAAEIbZYy1b8861.jpg

web.xml的信息

<servlet>
        <servlet-name>dispatcherServlet</servlet-name>
         <!-- 将服务器的控制权交给Spring -->
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet   
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
             <!-- 需要加载的配置文件 -->  
            <param-value>/WEB-INF/db-config.xml,/WEB-INF/web-config.xml</param-value>
        </init-param>
         <!-- 1表示服务器启动的时候就加载该类 -->
        <load-on-startup>1</load-on-startup>    
    </servlet>



    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
   <!-- 设置对那些请求进行控制,这里表示对所以以.do结尾的请求进行控制 -->
        <url-pattern>*.do</url-pattern>   
    </servlet-mapping>

db-config.xml的信息

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
    <!-- 引入jdbc配置文件 -->
    <!--<context:property-placeholder location="classpath:jdbc.properties" />-->

    <!--创建jdbc数据源 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" >
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/graduation_project?useUnicode=true&amp;characterEncoding=utf8" />
        <property name="username" value="root" />
        <property name="password" value="123456" />
    </bean>

    <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
    <!--<bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>-->

    <!-- 创建SqlSessionFactory,同时指定数据源 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="../xml-config.xml"></property>
        <property name="dataSource" ref="dataSource" />
    </bean>
    
    <!-- 可通过注解控制事务 -->
    <!--<tx:annotation-driven />-->

    <!-- Mapper接口所在包名,Spring会自动查找其下的Mapper -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="cn.edu.hnuc.dao" />
        <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> 
    </bean>
    
</beans>

web-config.xml的信息

<?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc" 
        xsi:schemaLocation="
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd "
    
    >
    
        <context:component-scan base-package="cn.edu.hnuc" >
        
        </context:component-scan>
        
         <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
        
        
        <!-- Controller方法调用规则定义 -->
        <bean id="paraMethodResolver"
            class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
            <property name="paramName" value="action"/>
            <property name="defaultMethodName" value="list"/>
        </bean>
      
       <!-- 页面View层基本信息设定 -->
        <bean id="viewResolver" 
              class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="viewClass"
                value="org.springframework.web.servlet.view.JstlView"/>
            <!--<property name="prefix" value="/myjsp/"/>-->
            <property name="suffix" value=".jsp"/>
        </bean>
    <!-- 有了注解后  这些就可以省略了 -->
    <!-- servlet映射列表,所有控制层Controller的servlet在这里定义,当加入MVC的注解功能后,不用 -->
        <!--<bean id="urlMapping"
              class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
            <property name="mappings">
                <props>
                    <prop key="city.do">cityController</prop>
                </props>
            </property>
        </bean>-->
    
    <!--<bean id="cityController" class="com.hnipo.controller.CityController">
        <property name="cityServices" ref="cityServices"></property>
    </bean>-->
    <mvc:interceptors>
        <mvc:interceptor>
                <mvc:mapping path="/*" />
                <!--<mvc:mapping path="/test/*" />-->
                <bean class="interceptor.InitInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
    

</beans>

上面完成了一个基础的配置,但是当自己写一个监听器实现ServletContextListener,实现类InitListener的信息如下

/**
 * 
 */
package cn.edu.hnuc.listener;

import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.log4j.Logger;

import cn.edu.hnuc.dao.ItemtypeMapper;
import cn.edu.hnuc.entity.MyList;
import cn.edu.hnuc.services.goodsView.MenuGenerator;

/** 功能介绍:
 * 
 * @author yyb
 * 时间2014-5-24下午03:50:52
 */
public class InitListener implements ServletContextListener{
    
    Logger log = Logger.getLogger(this.getClass());//与日志有关
    @Resource
    private MenuGenerator menuGenerator;//一个关于菜单生成类,主要功能就是从数据库中取出商品的分类信息
    //menuGenerator的getter和setter方法略
    public void contextDestroyed(ServletContextEvent servletcontextevent) {
        
    }
    public void contextInitialized(ServletContextEvent servletcontextevent) {
        System.out.println("监听器开始起作用了");  
        //得到商品信息的集合MyList是将分类信息中的重要成分封装成了一个类,可不必深入
        List<MyList> mainMenu = menuGenerator.getGoodsType(MenuGenerator.TYPE.FIRSTTYPE, null);
        ServletContext context = servletcontextevent.getServletContext();
        
        if(context.getAttribute("mainMenu")==null){
            context.setAttribute("mainMenu", mainMenu);
            for (MyList m : mainMenu) {
                log.debug("在监听器中增加的菜单项"+m.getFirstType());
            }
        }
    }
    
}

做了这一步,下面要做的就是到web.xml中添加监听器的信息。wKioL1OBsO3A8q-HAAD7M1DKySo662.jpg想想应该也就可以了,下面启动服务器

wKiom1OBs8aS8cf6AAQ8h7xezfQ684.jpg

这个有些无从下手了,问度年,问谷哥终于有了那么些线索SSH框架问题——listener(监听器)的配置报错:javax.naming.NameNotFoundException: Name com………… 下面对其关键信息进行截图

wKiom1OBtK6jdNH6AAIC6VbDgOM719.jpg

自己又开始捣鼓开始改代码。

在原来InitListener代码中的contextInitialized方法中增加这样几行,同时去掉注解@Resourse

wKiom1OBvL6jJlKaAACpguDHSLw773.jpg

再次启服,上次的问题是没有了,不过又有新问题了

wKiom1OBteCgMveRAAFrlIO9Dsc525.jpg

wKioL1OBtbSyOM4eAAEEgMUiUtA132.jpg

wKiom1OBteDwVyxMAADTxuCPmxY301.jpg

主要是因为WEB-INF/xml-config.xml没有找到,但在我最开始的文件布局中,这个文件是确实存在的。仔细分析一下WEB-INF/xml-config.xml是在db-config.xml中引用过,在使用ClassPathXmlApplicationContext的时候,它是在classpath路径下开始引用的,加载配置文件的时候是这样的new ClassPathXmlApplicationContext("../web-config.xml","../db-config.xml")。所以在db-config下也仍然是在classpath开始进行查找的,所以在db-config.xml 中改成如下

wKiom1OBt-2QLhg5AAENXosechU716.jpg

再次启动服务器

wKioL1OBuNjS6tNWAAOyR7zqVLA386.jpg

这回监听器没有报错了,倒是DispatcherServlet开始出问题了,而且又是说配置文件没有找到,这是几个意思啊,对此,我的看法是web.xml中加载的路径是用项目的根路径开始的,所以呢复制粘贴db-config.xml,命名为db-config2.xml,主要的不同如下

wKioL1OBu6Wz6vDyAADzV9Wi8dE344.jpg

在web.xml文件中也做相应的更改

wKiom1OBvCGDKpVwAACzsM4oo4o407.jpg

ok,问题算是告一段落了


总结:其实所有的这些问题好像很乱,其实究其原因还是对Spring了解的不深刻

下面对Spring中需要注意的几点进行提炼

  1. 注解的方式执行的位置,spring的注入是在filter和listener之后的,(顺序是这样的listener >>  filter >> servlet >>  spring )

  2. 如果如果在监听器中有需要对容器中bean进行引用,就不能采用注解的方式了。只能手动的进行配置文件的读取

  3. 注意使用ClassPathXmlApplicationContext使用classpath问文件的根路径,而在配置文件中使用路径一个为"/"表示在根路径下。需要回到上一级的目录采用"../",关于Spring读取配置文件的方式,Spring中加载xml配置文件的六种方式