Spring+MyBatis+SpringMvc整合Demo

客户关系管理系统demo

项目分析

该demo使用技术及环境:ssm+maven+bootstrap+jsp+mysql+idea+jdk1.8

需求:客户管理,实现客户列表分页显示如下图

项目开始

环境搭建

  1. 数据库环境:

    数据库与表:
    客户表

    字典表:[设计初衷 -- 将页面很多定义好且无需更改的字符串统一在字典表管理,优化数据库]

  2. pom.xml -- 引入所需jar

思考:整合:ssm+maven+mysql,需要哪些jar?

  • 数据库层:Mysql数据库连接驱动,mybatis相关jar,mybatis与spring整合需要的包

     <!-- mybatis -->
         <dependency>
             <groupId>org.mybatis</groupId>
             <artifactId>mybatis</artifactId>
             <version>3.2.3</version>
         </dependency>
     <!--spring和mybatis整合-->
         <dependency>
             <groupId>org.mybatis</groupId>
             <artifactId>mybatis-spring</artifactId>
             <version>1.2.1</version>
         </dependency>
     <!--驱动-->
         <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
             <version>5.1.6</version>
             <scope>runtime</scope>
         </dependency>
     <!--连接池-->
     	<dependency>
             <groupId>c3p0</groupId>
             <artifactId>c3p0</artifactId>
             <version>0.9.1.2</version>
         </dependency>
    
  • spring管理(已包含springmvc)

      <properties>
          <spring.version>4.2.4.RELEASE</spring.version>
          <slf4j.version>1.6.6</slf4j.version>
          <log4j.version>1.2.12</log4j.version>
      </properties>
    
      <dependencies>
          <!-- spring ++start++ -->
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-core</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-beans</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-context</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-orm</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-test</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-context-support</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-aop</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-web</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <!-- springmvc -->
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-webmvc</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <dependency>
              <groupId>org.aspectj</groupId>
              <artifactId>aspectjweaver</artifactId>
              <version>1.8.7</version>
          </dependency>
    
  • JSON相关

      <!--json-->
      <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-annotations</artifactId>
          <version>2.4.0</version>
      </dependency>
      <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-core</artifactId>
          <version>2.4.2</version>
      </dependency>
      <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>2.4.2</version>
      </dependency>
    
  • 日志相关

      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>${slf4j.version}</version>
      </dependency>
    
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>${slf4j.version}</version>
      </dependency>
    
  • 其他[如果使用idea开发,无自带的jstl标签库,需导入以下Jar坐标]

      <dependency>
          <groupId>jstl</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
      </dependency>
    
      <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>2.5</version>
          <scope>provided</scope>
      </dependency>
    
      <!--jsp引入,后面自定义分页标签会使用-->
      <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jsp-api</artifactId>
          <version>2.0</version>
          <scope>provided</scope>
      </dependency>
    
  • tomcat插件

      <build>
          <plugins>
              <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-compiler-plugin</artifactId>
                  <version>3.5.1</version>
                  <configuration>
                      <source>1.7</source>
                      <target>1.7</target>
                  </configuration>
              </plugin>
              <plugin>
                  <groupId>org.apache.tomcat.maven</groupId>
                  <artifactId>tomcat7-maven-plugin</artifactId>
                  <version>2.2</version>
                  <configuration>
                      <!-- 指定端口 -->
                      <port>9090</port>
                      <!-- 请求路径 -->
                      <path>/autoErp</path>
                      <!-- uri编码 -->
                      <uriEncoding>utf-8</uriEncoding>
                  </configuration>
              </plugin>
          </plugins>
    
    
      <!--注意!!!!!!!如果用的是IDEA开发,需配上该项,否则默认不会将mybatis的xml配置文件编译到target中-->
          <resources>
              <resource>
                  <directory>src/main/java</directory>
                  <includes>
                      <include>**/*.xml</include>
                  </includes>
                  <filtering>false</filtering>
              </resource>
          </resources>
      </build>
    
  1. 项目初始结构

  2. 项目三层建包结构和配置文件

mapper层:

mybatis配置文件[只需提供约束头,里面内容不用写]
mapper配置文件(接口.xml),写sql语句.
spring整合mapper配置文件 spring-mapper.xml

如下:

需求一:客户列表分页显示

DAO层开发 start

SQL

SELECT
c.cust_id,
c.cust_name,
a.dict_item_name as cust_source,
b.dict_item_name as cust_industry,
d.dict_item_name as cust_level,
c.cust_mobile,
c.cust_phone
FROM
	t_customer c
LEFT OUTER JOIN t_basedict a ON c.cust_source = a.dict_id
LEFT OUTER JOIN t_basedict b ON c.cust_industry = b.dict_id
LEFT OUTER JOIN t_basedict d ON c.cust_level = d.dict_id;

编写sqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>

编写 CustomerMapper接口

分析:

  1. 列表显示,且列表需要分页
  2. 参数:当前页,每页显示
  3. 返回值 集合,泛型是QueryVo -- 该类封装客户端列表所需要的数据(客户表和字典表)
  4. sql语句xml相关配置

QueryVo -- POJO类

public class QueryVo {
    private Integer cust_id;
    private String cust_name;
    private String cust_source;  //来源
    private String cust_industry;//行业
    private String cust_level;	 //级别
    private String cust_mobil;
    private String cust_phone;
	private Integer index;//分页开始
	private Integer rows;//数据条数

	//getter and setter method...

}

CustomerMapper中添加方法

	public interface CustomerMapper {
    /**
     * 查询客户列表
     * @param vo 条件对象
     * @return 库户列表
     */
    public List<QueryVo> getCustomerList(QueryVo vo);
}

配置xml

	<?xml version="1.0" encoding="UTF-8" ?>
	<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
	<mapper namespace="com.xingc.example.mapper.CustomerMapper">
	    <select id="getCustomerList" parameterType="com.xingc.example.pojo.QueryVo"
	            resultType="com.xingc.example.pojo.QueryVo">
	
	        SELECT
	            c.cust_id,
	            c.cust_name,
	            a.dict_item_name AS cust_source,
	            b.dict_item_name AS cust_industry,
	            d.dict_item_name AS cust_level,
	            c.cust_mobile,
	            c.cust_phone
	        FROM
	            t_customer c
	            LEFT OUTER JOIN t_basedict a ON c.cust_source = a.dict_id
	            LEFT OUTER JOIN t_basedict b ON c.cust_industry = b.dict_id
	            LEFT OUTER JOIN t_basedict d ON c.cust_level = d.dict_id
	
	        <where>
	            <if test="cust_name != null and cust_name != ''">
	                and c.custname LIKE '%${cust_name}%'
	            </if>
	            <if test="cust_source != null and cust_source != ''">
	                and cust_source = #{cust_source}
	            </if>
	            <if test="cust_industry != null and cust_industry != ''">
	                and cust_industry = #{cust_industry}
	            </if>
	            <if test="cust_level != null and cust_level != ''">
	                and cust_level = #{cust_level}
	            </if>
	        </where>
	        limit #{index},#{rows}
	    </select>
	</mapper>

添加db.propertis和log4j.properties配置文件

db.properties:数据库连接的基础配置//数据库,用户名,密码等
log4j.properties:LOG日志所需配置
  • db.properties

      driverClass=com.mysql.jdbc.Driver
      url=jdbc:mysql:///ssm
      ##注意!!!!!!!!这个user除了username作为变量名外都可以使用,但如果使用username,将会和系统中的username冲突,造成数据库无法连接成功.
      user=root
      password=
    
  • log4j.propertis

      ##设置日志记录到控制台的方式
      log4j.appender.s=org.apache.log4j.ConsoleAppender
      log4j.appender.s.Target=System.out
      log4j.appender.s.layout=org.apache.log4j.PatternLayout
      log4j.appender.s.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n
      
      ##设置日志记录到文件的方式
      log4j.appender.file=org.apache.log4j.FileAppender
      log4j.appender.file.File=mylog.log
      log4j.appender.file.layout=org.apache.log4j.PatternLayout
      log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n
      
      ##日志输出的级别,以及配置记录方案
      log4j.rootLogger=info, s
    

编写spring-mapper.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
	http://www.springframework.org/schema/util
	http://www.springframework.org/schema/util/spring-util-4.2.xsd">

	 <!--开启注解-->
	<context:component-scan base-package="com.xingc.example"/>

    <!--引入外部配置propertis文件-->
    <context:property-placeholder location="classpath:db.properties"/>

    <!--数据库连接池,这里使用c3p0连接池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${driverClass}"/>
        <property name="jdbcUrl" value="${url}"/>
        <property name="user" value="${user}"/>
        <property name="password" value="${password}"/>
    </bean>

    <!--spring来管理mybatis的session工厂-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:sqlMapConfig.xml"/>

        <!--使用包扫描即无需指定具体的xml文件,因此注释-->
        <!--<property name="mapperLocations">
            <array>
                <value>com/xingc/example/mapper/CustomerMapper.xml</value>
            </array>
        </property>-->
    </bean>

    <!--包扫描,所有mapper,此时spring将会管理mapper根据xml生成对应的代理类,取代理对象只需要使用@Autowired注解即可-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.xingc.example.mapper"></property>
    </bean>

</beans>

测试走一波

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-mapper.xml"})
public class CustomerMapperTest {
    @Autowired
    private CustomerMapper customerMapper;
    @Test
    public void test(){
        QueryVo vo = new QueryVo();
        vo.setIndex(0);
        vo.setRows(3);
        //查询第一页的三条记录
        List<QueryVo> customerList = customerMapper.getCustomerList(vo);
        System.out.println("\n+++结果数量: "+customerList.size());
        System.out.println("\n+++结果显示: "+customerList);
    }
}
  • 测试结果

  • 至此,mapper测试成功,开发基本完成[单一列表显示功能]

DAO层 end

Service层开发

在service/pom.xml中添加mapper层的jar依赖

    <dependencies>
        <dependency>
            <groupId>com.xingc.example</groupId>
            <artifactId>mapper</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

module结构

编写spring-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
	http://www.springframework.org/schema/util
	http://www.springframework.org/schema/util/spring-util-4.2.xsd">

    <!--需要配置的内容:事务[如果使用注解式申明事务,完全可以省略该配置,只需在需要事务的类或方法中配置@Transactional即可]-->
    <!--事务管理bean-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--前提是将mapper层的spring-mapper.xml也一起加载,否则该连接池无法使用,[web.xml中需同时加载spring-mapper.xml文件]-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--事务-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="udpate*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="select*" read-only="true"/>
            <tx:method name="get*" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!--增强切面-->
    <aop:config>
        <aop:pointcut id="myPoint" expression="execution(* com.xingc.example.service.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="myPoint"/>
    </aop:config>

</beans>

编写客户业务逻辑接口

	public interface CustomerService {
	    /**
	     * 查询客户列表
	     * @param vo 条件对象
	     * @return 库户列表
	     */
	    public List<QueryVo> getCustomerList(QueryVo vo);
	}

编写客户业务逻辑实现

//注意:使用该注解的前提是已经配置了 <context:component-scan base-package="com.xingc.example"/>

@Service("customerService")
public class CustomerServiceImpl implements CustomerService {
    @Autowired
    private CustomerMapper customerMapper;

    @Override
    public List<QueryVo> getCustomerList(QueryVo vo) {
        return customerMapper.getCustomerList(vo);
    }
}

测试再来一波

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:spring-*.xml"})
public class CustomerServiceTest {
    @Autowired
    private CustomerService customerService;

    @Test
    public void test() {
        QueryVo vo = new QueryVo();
        vo.setIndex(0);
        vo.setRows(3);
        //查询第一页的三条记录
        List<QueryVo> customerList = customerService.getCustomerList(vo);
        System.out.println("\n+++结果数量: " + customerList.size());
        System.out.println("\n+++结果显示: " + customerList);
    }
}
  • 结果

分页???

由于考虑到前端页面需要对客户列表进行分页,因此这里的业务逻辑需要修改

  • 添加分页实体

      	public class Page<T> {
      
      		private int total;
      		private int page;
      		private int size;
      	    private List<T> rows;
      		public int getTotal() {
      			return total;
      		}
      		public void setTotal(int total) {
      			this.total = total;
      		}
      		public int getPage() {
      			return page;
      		}
      		public void setPage(int page) {
      			this.page = page;
      		}
      		public int getSize() {
      			return size;
      		}
      		public void setSize(int size) {
      			this.size = size;
      		}
      		public List<T> getRows() {
      			return rows;
      		}
      		public void setRows(List<T> rows) {
      			this.rows = rows;
      		}    
          
      	}
    
  • 修改后的实现类和接口

      public interface CustomerService {
          /**
           * 查询客户列表
           * @param vo 条件对象
           * @return 库户列表
           */
          public Page<Customer> getCustomerList(QueryVo vo, Integer page, Integer rows);
      }
    
  • 实现

      @Service("customerService")
      public class CustomerServiceImpl implements CustomerService {
          @Autowired
          private CustomerMapper customerMapper;
      
          @Override
          public Page<Customer> getCustomerList(QueryVo vo, Integer page, Integer rows) {
              page = page == null ? page = 1 : page;
              rows = rows == null ? rows = 8 : rows;
              //分页处理
              vo.setIndex((page - 1) * rows);
              vo.setRows(rows);
      
              //获得数据库查出来的对象
              List<QueryVo> list = customerMapper.getCustomerList(vo);
              //循环封装
              Page p = new Page();
              p.setPage(page);
              p.setSize(rows);
              //总条数
              int total = customerMapper.getCount(vo);
              p.setTotal(total);
      
              List<Customer> customers = new ArrayList<>();
              Customer customer = null;
              for(QueryVo v : list){
                  customer = new Customer();
                  customer.setCust_id(v.getCust_id());
                  customer.setCust_name(v.getCust_name());
                  customer.setCust_source(v.getCust_source());
                  customer.setCust_industry(v.getCust_industry());
                  customer.setCust_level(v.getCust_level());
                  customer.setCust_mobile(v.getCust_mobil());
                  customer.setCust_phone(v.getCust_phone());
      
                  customers.add(customer);
              }
      
              p.setRows(customers);
              return p;
          }
      }
    

至此,service层开发基本完成,离实现越来越近啦.....

Web层开发开始

到了这里,想说一点,其实实际开发应该不是这样的步骤开发的,应该先把配置文件和项目架构搭起来,再从dao - service - web - 页面 依次实现,不过因为我是边写该笔记边开发,因此并未完全按照这个开发步骤来实现.叨逼叨结束...

springmvc.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.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">


    <!--开启注解-->
    <context:component-scan base-package="com.xingc.example"/>
    
    <!--默认使用springmvc的各种映射器/适配器等-->
    <mvc:annotation-driven/>

    <!--静态资源映射-->
    <mvc:resources mapping="/css/**" location="/css/"/>
    <mvc:resources mapping="/js/**" location="/js/"/>
	<mvc:resources mapping="/fonts/**" location="/fonts/"/>

    <!--试图解析器配置[解析xontroller的逻辑视图为物理视图,就是去哪里找jsp]-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

web.xml配置

<!DOCTYPE web-app PUBLIC
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>

    <!--spring-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring-*.xml</param-value>
    </context-param>

    <!--监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--springmvc-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--加载配置-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:springmvc.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

controller编写

@Controller
@RequestMapping("/cust/")
public class CustomerController {

    @Autowired
    private CustomerService customerService;

    @RequestMapping("/getCustomerList")
    public String getCustomerList(QueryVo vo,Integer page,Integer rows,Model model) {
        Page<Customer> p = customerService.getCustomerList(vo, page, rows);
        model.addAttribute("page",p);
        return "customer";
    }
}

测试

  • 说明:到这里,ssm配置及基本环境搭建完成,数据成功查出.列表显示后台部分完结,再看一下此时的项目结构

三层架构基本完成,开始前端jsp代码编写

JSP页面编写[jsp+bootstrap]

说明:在这里使用自定义标签的方式定义分页工具栏[和jstl标签是一个道理]

首先,创建jsp自定义标签,步骤如下

  1. 定义一个标签类

     /**
      * 显示格式 上一页 1 2 3 4 5 下一页
      */
     public class NavigationTag extends TagSupport {
         static final long serialVersionUID = 2372405317744358833L;
         
         /**
          * request 中用于保存Page<E> 对象的变量名,默认为“page”
          */
         private String bean = "page";
         
         /**
          * 分页跳转的url地址,此属性必须
          */
         private String url = null;
         
         /**
          * 显示页码数量
          */
         private int number = 5;
         
         @Override
         public int doStartTag() throws JspException {
             JspWriter writer = pageContext.getOut();
             HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
             Page page = (Page)request.getAttribute(bean); 
             if (page == null) 
                 return SKIP_BODY;
             url = resolveUrl(url, pageContext);
             try {
             	//计算总页数
             	int pageCount = page.getTotal() / page.getSize();
             	if (page.getTotal() % page.getSize() > 0) {
             		pageCount++;
             	}
             	writer.print("<nav><ul class=\"pagination\">");
                 //显示“上一页”按钮
             	if (page.getPage() > 1) {
                     String preUrl = append(url, "page", page.getPage() - 1);
                     preUrl = append(preUrl, "rows", page.getSize());
                     writer.print("<li><a href=\"" + preUrl + "\">上一页</a></li>");
                 } else {
                 	writer.print("<li class=\"disabled\"><a href=\"#\">上一页</a></li>");
                 }
                 //显示当前页码的前2页码和后两页码 
                 //若1 则 1 2 3 4 5, 若2 则 1 2 3 4 5, 若3 则1 2 3 4 5,
                 //若4 则 2 3 4 5 6 ,若10  则 8 9 10 11 12
                 int indexPage = (page.getPage() - 2 > 0)? page.getPage() - 2 : 1;  
                 for(int i=1; i <= number && indexPage <= pageCount; indexPage++, i++) {
                     if(indexPage == page.getPage()) {
                         writer.print( "<li class=\"active\"><a href=\"#\">"+indexPage+"<span class=\"sr-only\">(current)</span></a></li>");
                         continue;
                     }
                     String pageUrl  = append(url, "page", indexPage);
                     pageUrl = append(pageUrl, "rows", page.getSize());
                     writer.print("<li><a href=\"" + pageUrl + "\">"+ indexPage +"</a></li>");
                 }
                 //显示“下一页”按钮
                 if (page.getPage() < pageCount) {
                     String nextUrl  = append(url, "page", page.getPage() + 1);
                     nextUrl = append(nextUrl, "rows", page.getSize());
                     writer.print("<li><a href=\"" + nextUrl + "\">下一页</a></li>");
                 } else {
                 	writer.print("<li class=\"disabled\"><a href=\"#\">下一页</a></li>");
                 }
                 writer.print("</nav>");
             } catch (IOException e) {
                 e.printStackTrace();
             }
             return SKIP_BODY;
         }
         
         private String append(String url, String key, int value) {
     
             return append(url, key, String.valueOf(value));
         }
         
         /**
          * 为url 参加参数对儿
          * 
          * @param url
          * @param key
          * @param value
          * @return
          */
         private String append(String url, String key, String value) {
             if (url == null || url.trim().length() == 0) {
                 return "";
             }
     
             if (url.indexOf("?") == -1) {
                 url = url + "?" + key + "=" + value;
             } else {
                 if(url.endsWith("?")) {
                     url = url + key + "=" + value;
                 } else {
                     url = url + "&amp;" + key + "=" + value;
                 }
             }
             
             return url;
         }
         
         /**
          * 为url 添加翻页请求参数
          * 
          * @param url
          * @param pageContext
          * @return
          * @throws javax.servlet.jsp.JspException
          */
         private String resolveUrl(String url, javax.servlet.jsp.PageContext pageContext) throws JspException{
         	//UrlSupport.resolveUrl(url, context, pageContext)
         	Map params = pageContext.getRequest().getParameterMap();
         	for (Object key:params.keySet()) {
         		if ("page".equals(key) || "rows".equals(key)) continue;
         		Object value = params.get(key);
         		if (value == null) continue;
         		if (value.getClass().isArray()) {
         			url = append(url, key.toString(), ((String[])value)[0]);
         		} else if (value instanceof String) {
         			url = append(url, key.toString(), value.toString());
         		}
         	}
             return url;
         }
         
         
     
         /**
          * @return the bean
          */
         public String getBean() {
             return bean;
         }
     
         /**
          * @param bean the bean to set
          */
         public void setBean(String bean) {
             this.bean = bean;
         }
     
         /**
          * @return the url
          */
         public String getUrl() {
             return url;
         }
     
         /**
          * @param url the url to set
          */
         public void setUrl(String url) {
             this.url = url;
         }
     
         public void setNumber(int number) {
             this.number = number;
         }
         
     }
    
  2. 创建对应tld文件

     <?xml version="1.0" encoding="UTF-8" ?>
     <!DOCTYPE taglib
       PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
       "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
     <taglib>
     	<tlib-version>2.0</tlib-version>
     	<jsp-version>1.2</jsp-version>
     	<short-name>common</short-name>
     	<uri>http://xingc.com.cn/common/</uri>
     	<display-name>Common Tag</display-name>
     	<description>Common Tag library</description>
     
     	<tag>
     		<name>page</name>
     		<tag-class>com.xingc.example.utils.NavigationTag</tag-class>
     		<body-content>JSP</body-content>
     		<description>create navigation for paging</description>
     		<attribute>
     			<name>bean</name>
     			<rtexprvalue>true</rtexprvalue>
     		</attribute>
     		<attribute>
     			<name>number</name>
     			<rtexprvalue>true</rtexprvalue>
     		</attribute>
     		<attribute>
     			<name>url</name>
     			<required>true</required>
     			<rtexprvalue>true</rtexprvalue>
     		</attribute>
     	</tag>
     </taglib>
    
  3. 使用时,只需要引入 uri="http://xingc.com.cn/common/" 即可使用该标签

JSP页面customer.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
     pageEncoding="UTF-8" isELIgnored="false"%>
<%@ page trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="xingc" uri="http://xingc.com.cn/common/" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
            + path + "/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>客户列表-BootCRM</title>

    <!-- Bootstrap Core CSS -->
    <link href="<%=basePath%>css/bootstrap.min.css" rel="stylesheet">

    <!-- MetisMenu CSS -->
    <link href="<%=basePath%>css/metisMenu.min.css" rel="stylesheet">

    <!-- DataTables CSS -->
    <link href="<%=basePath%>css/dataTables.bootstrap.css" rel="stylesheet">

    <!-- Custom CSS -->
    <link href="<%=basePath%>css/sb-admin-2.css" rel="stylesheet">

    <!-- Custom Fonts -->
    <link href="<%=basePath%>css/font-awesome.min.css" rel="stylesheet"
          type="text/css">
    <link href="<%=basePath%>css/boot-crm.css" rel="stylesheet"
          type="text/css">

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
    <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

</head>

<body>

<div id="wrapper">

    <!-- Navigation -->
    <nav class="navbar navbar-default navbar-static-top" role="navigation"
         style="margin-bottom: 0">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse"
                    data-target=".navbar-collapse">
                <span class="sr-only">Toggle navigation</span> <span
                    class="icon-bar"></span> <span class="icon-bar"></span> <span
                    class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="index.html">BOOT客户管理系统 v2.0</a>
        </div>
        <!-- /.navbar-header -->

        <ul class="nav navbar-top-links navbar-right">
            <li class="dropdown"><a class="dropdown-toggle"
                                    data-toggle="dropdown" href="#"> <i class="fa fa-envelope fa-fw"></i>
                <i class="fa fa-caret-down"></i>
            </a>
                <ul class="dropdown-menu dropdown-messages">
                    <li><a href="#">
                        <div>
                            <strong>令狐冲</strong> <span class="pull-right text-muted">
									<em>昨天</em>
								</span>
                        </div>
                        <div>今天晚上向大哥找我吃饭,讨论一下去梅庄的事...</div>
                    </a></li>
                    <li class="divider"></li>
                    <li><a class="text-center" href="#"> <strong>查看全部消息</strong>
                        <i class="fa fa-angle-right"></i>
                    </a></li>
                </ul> <!-- /.dropdown-messages --></li>
            <!-- /.dropdown -->
            <li class="dropdown"><a class="dropdown-toggle"
                                    data-toggle="dropdown" href="#"> <i class="fa fa-tasks fa-fw"></i>
                <i class="fa fa-caret-down"></i>
            </a>
                <ul class="dropdown-menu dropdown-tasks">
                    <li><a href="#">
                        <div>
                            <p>
                                <strong>任务 1</strong> <span class="pull-right text-muted">完成40%</span>
                            </p>
                            <div class="progress progress-striped active">
                                <div class="progress-bar progress-bar-success"
                                     role="progressbar" aria-valuenow="40" aria-valuemin="0"
                                     aria-valuemax="100" style="width: 40%">
                                    <span class="sr-only">完成40%</span>
                                </div>
                            </div>
                        </div>
                    </a></li>
                    <li class="divider"></li>
                    <li><a href="#">
                        <div>
                            <p>
                                <strong>任务 2</strong> <span class="pull-right text-muted">完成20%</span>
                            </p>
                            <div class="progress progress-striped active">
                                <div class="progress-bar progress-bar-info" role="progressbar"
                                     aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"
                                     style="width: 20%">
                                    <span class="sr-only">完成20%</span>
                                </div>
                            </div>
                        </div>
                    </a></li>
                    <li class="divider"></li>
                    <li><a class="text-center" href="#"> <strong>查看所有任务</strong>
                        <i class="fa fa-angle-right"></i>
                    </a></li>
                </ul> <!-- /.dropdown-tasks --></li>
            <!-- /.dropdown -->
            <li class="dropdown"><a class="dropdown-toggle"
                                    data-toggle="dropdown" href="#"> <i class="fa fa-bell fa-fw"></i>
                <i class="fa fa-caret-down"></i>
            </a>
                <ul class="dropdown-menu dropdown-alerts">
                    <li><a href="#">
                        <div>
                            <i class="fa fa-comment fa-fw"></i> 新回复 <span
                                class="pull-right text-muted small">4分钟之前</span>
                        </div>
                    </a></li>
                    <li class="divider"></li>
                    <li><a href="#">
                        <div>
                            <i class="fa fa-envelope fa-fw"></i> 新消息 <span
                                class="pull-right text-muted small">4分钟之前</span>
                        </div>
                    </a></li>
                    <li class="divider"></li>
                    <li><a href="#">
                        <div>
                            <i class="fa fa-tasks fa-fw"></i> 新任务 <span
                                class="pull-right text-muted small">4分钟之前</span>
                        </div>
                    </a></li>
                    <li class="divider"></li>
                    <li><a href="#">
                        <div>
                            <i class="fa fa-upload fa-fw"></i> 服务器重启 <span
                                class="pull-right text-muted small">4分钟之前</span>
                        </div>
                    </a></li>
                    <li class="divider"></li>
                    <li><a class="text-center" href="#"> <strong>查看所有提醒</strong>
                        <i class="fa fa-angle-right"></i>
                    </a></li>
                </ul> <!-- /.dropdown-alerts --></li>
            <!-- /.dropdown -->
            <li class="dropdown"><a class="dropdown-toggle"
                                    data-toggle="dropdown" href="#"> <i class="fa fa-user fa-fw"></i>
                <i class="fa fa-caret-down"></i>
            </a>
                <ul class="dropdown-menu dropdown-user">
                    <li><a href="#"><i class="fa fa-user fa-fw"></i> 用户设置</a></li>
                    <li><a href="#"><i class="fa fa-gear fa-fw"></i> 系统设置</a></li>
                    <li class="divider"></li>
                    <li><a href="login.html"><i class="fa fa-sign-out fa-fw"></i>
                        退出登录</a></li>
                </ul> <!-- /.dropdown-user --></li>
            <!-- /.dropdown -->
        </ul>
        <!-- /.navbar-top-links -->

        <div class="navbar-default sidebar" role="navigation">
            <div class="sidebar-nav navbar-collapse">
                <ul class="nav" id="side-menu">
                    <li class="sidebar-search">
                        <div class="input-group custom-search-form">
                            <input type="text" class="form-control" placeholder="查询内容...">
                            <span class="input-group-btn">
								<button class="btn btn-default" type="button">
									<i class="fa fa-search" style="padding: 3px 0 3px 0;"></i>
								</button>
							</span>
                        </div> <!-- /input-group -->
                    </li>
                    <li><a href="customer.action" class="active"><i
                            class="fa fa-edit fa-fw"></i> 客户管理</a></li>
                    <li><a href="salevisit.action"><i
                            class="fa fa-dashboard fa-fw"></i> 客户拜访</a></li>
                </ul>
            </div>
            <!-- /.sidebar-collapse -->
        </div>
        <!-- /.navbar-static-side --> </nav>

    <div id="page-wrapper">
        <div class="row">
            <div class="col-lg-12">
                <h1 class="page-header">客户管理</h1>
            </div>
            <!-- /.col-lg-12 -->
        </div>
        <!-- /.row -->
        <div class="panel panel-default">
            <div class="panel-body">
                <form class="form-inline" action="${pageContext.request.contextPath }/customer/list.action"
                      method="get">
                    <div class="form-group">
                        <label for="customerName">客户名称</label>
                        <input type="text" class="form-control" id="customerName" value="${custName }" name="custName">
                    </div>
                    <div class="form-group">
                        <label for="customerFrom">客户来源</label>
                        <select class="form-control" id="customerFrom" placeholder="客户来源" name="custSource">
                            <option value="">--请选择--</option>
                            <c:forEach items="${fromType}" var="item">
                                <option value="${item.dict_id}"<c:if
                                        test="${item.dict_id == custSource}"> selected</c:if>>${item.dict_item_name }</option>
                            </c:forEach>
                        </select>
                    </div>
                    <div class="form-group">
                        <label for="custIndustry">所属行业</label>
                        <select class="form-control" id="custIndustry" name="custIndustry">
                            <option value="">--请选择--</option>
                            <c:forEach items="${industryType}" var="item">
                                <option value="${item.dict_id}"<c:if
                                        test="${item.dict_id == custIndustry}"> selected</c:if>>${item.dict_item_name }</option>
                            </c:forEach>
                        </select>
                    </div>
                    <div class="form-group">
                        <label for="custLevel">客户级别</label>
                        <select class="form-control" id="custLevel" name="custLevel">
                            <option value="">--请选择--</option>
                            <c:forEach items="${levelType}" var="item">
                                <option value="${item.dict_id}"<c:if
                                        test="${item.dict_id == custLevel}"> selected</c:if>>${item.dict_item_name }</option>
                            </c:forEach>
                        </select>
                    </div>
                    <button type="submit" class="btn btn-primary">查询</button>
                </form>
            </div>
        </div>
        <div class="row">
            <div class="col-lg-12">
                <div class="panel panel-default">
                    <div class="panel-heading">客户信息列表</div>
                    <!-- /.panel-heading -->
                    <table class="table table-bordered table-striped">
                        <thead>
                        <tr>
                            <th>ID</th>
                            <th>客户名称</th>
                            <th>客户来源</th>
                            <th>客户所属行业</th>
                            <th>客户级别</th>
                            <th>固定电话</th>
                            <th>手机</th>
                            <th>操作</th>
                        </tr>
                        </thead>
                        <tbody>
                        <c:forEach items="${page.rows}" var="row">
                            <tr>
                                <td>${row.cust_id}</td>
                                <td>${row.cust_name}</td>
                                <td>${row.cust_source}</td>
                                <td>${row.cust_industry}</td>
                                <td>${row.cust_level}</td>
                                <td>${row.cust_phone}</td>
                                <td>${row.cust_mobile}</td>
                                <td>
                                    <a href="#" class="btn btn-primary btn-xs" data-toggle="modal"
                                       data-target="#customerEditDialog" onclick="editCustomer(${row.cust_id})">修改</a>
                                    <a href="#" class="btn btn-danger btn-xs" onclick="deleteCustomer(${row.cust_id})">删除</a>
                                </td>
                            </tr>
                        </c:forEach>
                        </tbody>
                    </table>
                    <div class="col-md-12 text-right">
                        <itcast:page url="${pageContext.request.contextPath }/customer/list.action"/>
                    </div>
                    <!-- /.panel-body -->
                </div>
                <!-- /.panel -->
            </div>
            <!-- /.col-lg-12 -->
        </div>
    </div>
    <!-- /#page-wrapper -->

</div>
<!-- 客户编辑对话框 -->
<div class="modal fade" id="customerEditDialog" tabindex="-1" role="dialog"
     aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
                <h4 class="modal-title" id="myModalLabel">修改客户信息</h4>
            </div>
            <div class="modal-body">
                <form class="form-horizontal" id="edit_customer_form">
                    <input type="hidden" id="edit_cust_id" name="cust_id"/>
                    <div class="form-group">
                        <label for="edit_customerName" class="col-sm-2 control-label">客户名称</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="edit_customerName" placeholder="客户名称"
                                   name="cust_name">
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="edit_customerFrom" style="float:left;padding:7px 15px 0 27px;">客户来源</label>
                        <div class="col-sm-10">
                            <select class="form-control" id="edit_customerFrom" placeholder="客户来源" name="cust_source">
                                <option value="">--请选择--</option>
                                <c:forEach items="${fromType}" var="item">
                                    <option value="${item.dict_id}"<c:if
                                            test="${item.dict_id == custSource}"> selected</c:if>>${item.dict_item_name }</option>
                                </c:forEach>
                            </select>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="edit_custIndustry" style="float:left;padding:7px 15px 0 27px;">所属行业</label>
                        <div class="col-sm-10">
                            <select class="form-control" id="edit_custIndustry" name="cust_industry">
                                <option value="">--请选择--</option>
                                <c:forEach items="${industryType}" var="item">
                                    <option value="${item.dict_id}"<c:if
                                            test="${item.dict_id == custIndustry}"> selected</c:if>>${item.dict_item_name }</option>
                                </c:forEach>
                            </select>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="edit_custLevel" style="float:left;padding:7px 15px 0 27px;">客户级别</label>
                        <div class="col-sm-10">
                            <select class="form-control" id="edit_custLevel" name="cust_level">
                                <option value="">--请选择--</option>
                                <c:forEach items="${levelType}" var="item">
                                    <option value="${item.dict_id}"<c:if
                                            test="${item.dict_id == custLevel}"> selected</c:if>>${item.dict_item_name }</option>
                                </c:forEach>
                            </select>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="edit_linkMan" class="col-sm-2 control-label">联系人</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="edit_linkMan" placeholder="联系人"
                                   name="cust_linkman">
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="edit_phone" class="col-sm-2 control-label">固定电话</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="edit_phone" placeholder="固定电话"
                                   name="cust_phone">
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="edit_mobile" class="col-sm-2 control-label">移动电话</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="edit_mobile" placeholder="移动电话"
                                   name="cust_mobile">
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="edit_zipcode" class="col-sm-2 control-label">邮政编码</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="edit_zipcode" placeholder="邮政编码"
                                   name="cust_zipcode">
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="edit_address" class="col-sm-2 control-label">联系地址</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="edit_address" placeholder="联系地址"
                                   name="cust_address">
                        </div>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
                <button type="button" class="btn btn-primary" onclick="updateCustomer()">保存修改</button>
            </div>
        </div>
    </div>
</div>
<!-- /#wrapper -->

<!-- jQuery -->
<script src="<%=basePath%>js/jquery.min.js"></script>

<!-- Bootstrap Core JavaScript -->
<script src="<%=basePath%>js/bootstrap.min.js"></script>

<!-- Metis Menu Plugin JavaScript -->
<script src="<%=basePath%>js/metisMenu.min.js"></script>

<!-- DataTables JavaScript -->
<script src="<%=basePath%>js/jquery.dataTables.min.js"></script>
<script src="<%=basePath%>js/dataTables.bootstrap.min.js"></script>

<!-- Custom Theme JavaScript -->
<script src="<%=basePath%>js/sb-admin-2.js"></script>

<script type="text/javascript">
    function editCustomer(id) {
        $.ajax({
            type: "get",
            url: "<%=basePath%>customer/edit.action",
            data: {"id": id},
            success: function (data) {
                $("#edit_cust_id").val(data.cust_id);
                $("#edit_customerName").val(data.cust_name);
                $("#edit_customerFrom").val(data.cust_source)
                $("#edit_custIndustry").val(data.cust_industry)
                $("#edit_custLevel").val(data.cust_level)
                $("#edit_linkMan").val(data.cust_linkman);
                $("#edit_phone").val(data.cust_phone);
                $("#edit_mobile").val(data.cust_mobile);
                $("#edit_zipcode").val(data.cust_zipcode);
                $("#edit_address").val(data.cust_address);

            }
        });
    }
    function updateCustomer() {
        $.post("<%=basePath%>customer/update.action", $("#edit_customer_form").serialize(), function (data) {
            alert("客户信息更新成功!");
            window.location.reload();
        });
    }

    function deleteCustomer(id) {
        if (confirm('确实要删除该客户吗?')) {
            $.post("<%=basePath%>customer/delete.action", {"id": id}, function (data) {
                alert("客户删除更新成功!");
                window.location.reload();
            });
        }
    }
</script>

</body>

</html>

测试结果

访问http://localhost:8080/crmByssm/cust/getCustomerList

客户列表成功显示

说两句

我现在正在学ssm框架,水平不够,如果有什么bug,还请见谅,本来打算写一下条件查询和修改,删除等功能的,但到这里发现自己写了很多,就不赘述了.因为环境搭建好后,别的功能就相对简单一些.

posted @ 2017-09-04 14:52  星尘h  阅读(219)  评论(0编辑  收藏  举报