根据我的上一篇文章呢,创建了一个完整的基于maven的web项目,那么下一步就是搭建一个基本的ssm框架了
首先,spring:一个轻量级的Java框架;springMvc:一个基于springframeWork的后续产品;myBatis:基于Java的持久层框架。
1、前期准备工作,创建一个库,创建表
我用的电脑系统是Windows系统,官网下载的mysql。
mysql操作工具,用的mysql workbench,一款免费的mysql操作工具
创建一个库,暂定为test,创建表tb_user(user_id,user_name,user_password,user_email)
随便插入点数据,以备后面使用
2、框架包依赖的的整合
打开pom文件,修改pom文件
项目主要依赖的jar包有Spring核心包、Spring AOP包、Spring MVC包、MyBatis ORM包、MyBatis-Spring适配包、数据库连接池、JSTL、JUnit、Log4j2等,具体的pom.xml文件如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zhz.test</groupId>
<artifactId>test</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>test Maven Webapp</name>
<url>http://maven.apache.org</url>
<!-- 引入包的版本号变量 -->
<properties>
<!-- spring版本号 -->
<spring.version>3.2.9.RELEASE</spring.version>
<!-- log4j日志文件管理包版本 -->
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<!-- junit版本号 -->
<junit.version>4.11</junit.version>
<!-- mybatis版本号 -->
<mybatis.version>3.2.1</mybatis.version>
</properties>
<dependencies>
<!-- servlet依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!--单元测试依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- 添加Spring依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</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-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-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!--spring单元测试依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- 日志文件管理包 -->
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</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>
<!-- log end -->
<!--mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- mybatis/spring包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.0</version>
</dependency>
<!-- mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.29</version>
</dependency>
<!--c3p0 连接池 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- aspectJ AOP 织入器 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<!--文件上传 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
<build>
<finalName>test</finalName>
</build>
</project>
完成后,保存pom文件,可以看到eclipse开始更新项目,下载依赖包
这个时刻再看就可以发现项目已经没有了报错信息提示等,是因为导入了对应了servlet包,所以index.jsp不报错了。
3、创建配置文件
在resources目录下,创建对应的数据库连接配置文件,config.properties
mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
mysql.user=root
mysql.password=123456
mysql.acquireIncrement=5
mysql.initialPoolSize=10
mysql.minPoolSize=5
mysql.maxPoolSize=20
创建spring-mybatis.xml整合mybatis
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- 1.引入属性文件 -->
<context:property-placeholder location="classpath:config.properties" />
<!-- 2.自动扫描service包(自动注入) -->
<context:component-scan base-package="com.demo.service" />
<!-- ========================================配置数据源========================================= -->
<!-- 3.配置C3P0数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<!--驱动类名 -->
<property name="driverClass" value="${mysql.driver}" />
<!-- url -->
<property name="jdbcUrl" value="${mysql.url}" />
<!-- 用户名 -->
<property name="user" value="${mysql.user}" />
<!-- 密码 -->
<property name="password" value="${mysql.password}" />
<!-- 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数 -->
<property name="acquireIncrement" value="${mysql.acquireIncrement}"></property>
<!-- 初始连接池大小 -->
<property name="initialPoolSize" value="${mysql.initialPoolSize}"></property>
<!-- 连接池中连接最小个数 -->
<property name="minPoolSize" value="${mysql.minPoolSize}"></property>
<!-- 连接池中连接最大个数 -->
<property name="maxPoolSize" value="${mysql.maxPoolSize}"></property>
</bean>
<!-- ========================================针对myBatis的配置项============================== -->
<!-- 4.配置sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 实例化sqlSessionFactory时需要使用上述配置好的数据源以及SQL映射文件 -->
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- sql映射文件路径 -->
<!-- 自动扫描com/demo/mapping/目录下的所有SQL映射的xml文件, 省掉Configuration.xml里的手工配置
value="classpath:com/demo/mapping/*.xml"指的是classpath(类路径)下com.demo.mapping包中的所有xml文件 -->
<property name="mapperLocations" value="classpath:com/demo/mapping/*.xml" />
</bean>
<!-- 5.配置扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 扫描com.demo.dao这个包以及它的子包下的所有映射接口类 -->
<property name="basePackage" value="com.demo.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
<!-- ========================================配置事务============================== -->
<!-- 6.声明式事务管理 -->
<!--定义事物管理器,由spring管理事务 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 配置数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
创建spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd" >
<!-- 1.自动扫描包,实现支持注解的IOC -->
<!-- 自动扫描该包,使springmvc认为包下用了@Controller注解的类是控制器 -->
<context:component-scan base-package="com.demo.controller" />
<!-- 2.配置注解的处理器映射器和处理器适配器 -->
<!-- <mvc:annotation-driven /> 是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学者
快速应用默认配置方案。<mvc:annotation-driven /> 会自动注册DefaultAnnotationHandlerMapping与
AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的。 -->
<mvc:annotation-driven />
<!-- 3.Spring MVC不处理静态资源 -->
<mvc:default-servlet-handler/>
<!-- 4.配置内部视图解析器 -->
<!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<!--5.配置文件上传解析器 -->
<!--Spring MVC默认不能识别multipart格式的文件内容 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
</beans>
修改web.xml
<web-app id="WebApp_ID" version="3.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<!-- 加载spring和mybatis的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mybatis.xml</param-value>
</context-param>
<!-- 使用ContextLoaderListener初始化Spring容器 -->
<!--若没有指定其他参数,默认查找的配置文件位置是:/WEB-INF/applicationContext.xml -->
<listener>
<description>Spring容器加载监听器</description>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置springmvc核心控制器 -->
<!-- spring MVC servlet -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<description>spring MVC 配置文件路径</description>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!-- 启动动优先级,越小越早加载 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Servlet访问的路径映射,所有的访问都必须经过调度用的前置控制器 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--编码过滤器 -->
<filter>
<description>字符集过滤器</description>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<description>字符集编码</description>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<!-- 路径映射 -->
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
4、完善项目结构,生成实体类
在实际开发中,因为对应的表实在太多,手写太麻烦,我们考虑使用mybatis generator来自动生成。
<!-- Mybatis Generator -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
但是我又不想在项目中添加这些冗余的代码,怎么办?我思考了下,于是新建了一个本地简单的Java项目
我在项目中,导入了三个jar包,mybatis-3.21.jar、mybatis-generator-core-1.32.jar、mysql-connector-java-5.1.34.jar
然后再src下面建立一个文件generator.xml(注意配置本地mysql jar包的路径),
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 数据库驱动 -->
<classPathEntry location="D:\java_workspaces\mybatis-generator\mysql-connector-java-5.1.34.jar" />
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressDate" value="true" />
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库链接URL,用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/test"
userId="root" password="123456">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 生成模型的包名和位置 -->
<javaModelGenerator targetPackage="com.demo.model"
targetProject="src">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- 生成映射文件的包名和位置 -->
<sqlMapGenerator targetPackage="com.demo.mapping"
targetProject="src">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- 生成DAO的包名和位置 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.demo.dao"
targetProject="src">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名 -->
<table tableName="tb_user" domainObjectName="User"
enableCountByExample="fasle" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false" >
</table>
</context>
</generatorConfiguration>
建立一个包名字叫com.demo.test,里面建立个类
package com.demo.test;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;
public class MybatisGeneratorTest {
public static void main(String[] args)
throws IOException, XMLParserException, InvalidConfigurationException, SQLException, InterruptedException {
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
//读取配置文件generatorConfig.xml
File configFile = new File("src/generator.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
for (String s : warnings) {
System.out.println(s);
}
}
}
在xml里面配置好对应的生成包的路径,然后运行main方法,发现生成了对应的代码,很完美的不开了在开发项目中添加这些冗余的代码,对不对,我所做的只需要添加一个copy的工作。然后在此基础上做一些个性化的操作,比如分页查询等
/**
* 查询用户信息并分页
* @param skip
* @param size
* @return
*/
public List<User> queryUserPager(@Param("skip") int skip,@Param("size") int size);
/**
* 查询用户总数
* @return
*/
public int queryUserCount();
/**
* 删除多个用户
* @param userIds
* @return
*/
public int deleteUsers(int[] userIds);
<!--查询用户信息并分页 -->
<select id="queryUserPager" resultMap="BaseResultMap">
select t.user_id,t.user_name,t.user_sex,date_format(t.user_birthday,'%Y-%m-%d')user_birthday,
t.user_email,t.user_edu,t.user_telephone,t.user_address,p.codedesc as user_sex_desc,
p1.codedesc as user_edu_desc
from tb_user t inner join tb_dict p on t.user_sex=p.code and p.field='SEX'
inner join tb_dict p1 on t.user_edu = p1.code and p1.field = 'EDU'
order by t.create_time desc
limit #{skip},#{size}
</select>
<!--查询用户总数 -->
<select id="queryUserCount" resultType="int">
select count(*) from tb_user
</select>
<!--删除多个用户 -->
<delete id="deleteUsers" parameterType="java.util.List">
delete from tb_user where user_id in
<!-- <foreach>标签有循环的功能,可以用来生成有规律的SQL语句,主要属性有:
item:表示集合每一个元素进行迭代时的别名
index:表示在迭代过程中,每次迭代到的位置
open:表示该语句以什么开始
separator:表示每次迭代之间以什么符号作为分隔
close:表示该语句以什么结束
collection:要循环的集合 -->
<foreach item="item" index="index" collection="array" open="(" separator="," close=")">
#{item}
</foreach>
</delete>
5、完善服务层
写上对应的服务接口,实现等。注意服务接口要写在配置的xml文件对应的包里面
6、完善控制层
参考:https://www.cnblogs.com/xiaoxi/p/6260628.html
控制层实现一个简单的查询列表方法
package com.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.demo.service.IUserService;
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 日志打印器
*/
private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);
@Autowired
private IUserService userService;
/**
* 查询用户信息
* @param model
* @param pageNO
*/
@RequestMapping("/list")
public void list(Model model,@RequestParam(required=false,defaultValue="1") int pageNO){
try {
LOGGER.info("查询用户列表信息,入参pageNo:{0}",pageNO);
int size=5;
model.addAttribute("success",true);
model.addAttribute("size",size);
model.addAttribute("pageNO",pageNO);
model.addAttribute("count",userService.queryUserCount());
model.addAttribute("userList", userService.queryUserPager(pageNO, size));
LOGGER.info("查询用户列表信息完成");
} catch (Exception e) {
// TODO: handle exception
LOGGER.info("查询用户列表信息异常,"+e.getMessage());
model.addAttribute("success", false);
model.addAttribute("errorMsg", "查询列表失败");
}
}
}
然后完善对应的页面,我们在webapp下面新建文件夹view/user,在文件夹下面新建list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="<c:url value="/styles/main.css"/>" type="text/css" rel="stylesheet" />
<title>用户管理</title>
</head>
<body>
<div class="main">
<h2 class="title"><span>用户管理</span></h2>
<form action="deleteUsers" method="post">
<table border="1" width="100%" class="tab">
<tr>
<th><input type="checkbox" id="chkAll"></th>
<th>姓名</th>
<th>性别</th>
<th>出生日期</th>
<th>邮箱</th>
<th>学历</th>
<th>联系方式</th>
<th>家庭住址</th>
<th>操作</th>
</tr>
<c:forEach var="entity" items="${userList}">
<tr>
<th><input type="checkbox" name="user_id" value="${entity.user_id}"></th>
<td>${entity.user_name}</td>
<td>${entity.user_sex_desc}</td>
<td>${entity.user_birthday}</td>
<td>${entity.user_email}</td>
<td>${entity.user_edu_desc}</td>
<td>${entity.user_telephone}</td>
<td>${entity.user_address}</td>
<td>
<a href="edit/${entity.user_id}" class="abtn">编辑</a>
<a href="deleteUserById/${entity.user_id}" class="abtn">删除</a>
</td>
</tr>
</c:forEach>
</table>
<div id="pager"></div>
<p>
<a href="add" class="abtn out">添加</a>
<input type="submit" value="批量删除" class="btn out" οnclick="return submitForm();"/>
</p>
<p style="color: red">${message}</p>
<!--分页 -->
<script type="text/javascript" src="<c:url value="/scripts/jQuery1.11.3/jquery-1.11.3.min.js"/>" ></script>
<link href="<c:url value="/scripts/pagination22/pagination.css"/>" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="<c:url value="/scripts/pagination22/jquery.pagination2.2.js"/>" ></script>
<script type="text/javascript">
$(document).ready(function(){
//全选/取消全选
$("#chkAll").click(function(){
var checked=$("#chkAll").prop("checked");
$("input[name='user_id']").prop("checked",checked);
})
})
//初始化分页组件
var count=${count};
var size=${size};
var pageNO=${pageNO};
$("#pager").pagination(count, {
items_per_page:size,
current_page:pageNO-1,
next_text:"下一页",
prev_text:"上一页",
num_edge_entries:2,
load_first_page:false,
callback:handlePaginationClick
});
//回调方法
function handlePaginationClick(new_page_index, pagination_container){
location.href="list?pageNO="+(new_page_index+1);
}
function submitForm(){
if($("input[name='user_id']:checked").length==0){
alert("请选择要删除的记录!");
return false;
}
return true;
}
</script>
</form>
</div>
</body>
</html>
然后开始测试,测试所用的是Tomcat,但是发现从eclipse中打开无法访问。
检查原因,发现项目没有发布
然后网上查询,发现是eclipse重定向了,导致的,参考文档:
https://blog.csdn.net/new_clumsybird/article/details/51881754
修改对应的eclipse配置Tomcat
这个时候重新测试发现网页打开有问题,后台日志输出也不详细,考虑服务层有问题,然后打算写一个测试类。
6、测试类的编写
在test/java下面新建一个包,然后建立一个基础测试类叫SpringTestCase.java,一个用户测试类。
package com.demo.service.test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//指定bean注入的配置文件
@ContextConfiguration(locations = { "classpath:spring-mybatis.xml" })
//使用标准的JUnit @RunWith注释来告诉JUnit使用Spring TestRunner
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringTestCase extends AbstractJUnit4SpringContextTests {
protected Logger logger = LoggerFactory.getLogger(getClass());
}
package com.demo.service.test;
import java.util.List;
import org.junit.Test;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import com.demo.dao.UserMapper;
import com.demo.model.User;
import com.demo.service.IUserService;
public class UserServiceImplTest extends SpringTestCase {
@Autowired
private IUserService userService;
@Test
public void queryUserPager(){
// TODO Auto-generated method stub
try {
List<User> list= userService.queryUserPager(1, 10);
logger.debug("查询到的用户信息如下:"+list);
} catch (Exception e) {
// TODO: handle exception
logger.debug("查询到的用户信息报错:"+e);
}
}
@Test
public void queryUserCount() {
// TODO Auto-generated method stub
int count = userService.queryUserCount();
logger.debug("查询用户总数:"+count);
}
}
然后右击测试类方法,选择debug——junit Test。控制台打印出结果,这个时候发现了一些问题存在。
java.lang.Exception: DEBUG STACK TRACE for PoolBackedDataSource.close().
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.close(AbstractPoolBackedDataSource.java:417)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
......
java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:566)
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:234)
.....
报这个错误,查询得知,这种情况,一种是对应的服务没有注入。检查得知注入了。另一种呢,就是DataSource配置文件有问题
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
这句话,Spring在读取这个配置文件以后,需要根据这些信息来实例化一些类,然后内部再根据中间的那些配置信息来实际
构造数据源。可是来了个问题。不能保证这里的ComboPooledDataSource数据源一定是可用的,
也不能保证close方法一定能关闭连接,对吧?Spring本身不能检查这个类是否 真实有效,毫无Bug。
实际上呢,也检查不了。同样的,close方法是否有效,也需要进行检查。
那么干掉destroy-method这个参数,然后再次测试,又发生了点别的小问题,对应的对象类,缺少两个参数,从mapping配置文件里面,我添加的sql中对应的字段找不到,这是个小问题,在对象中添加好就可以啦。OK,现在测试通过,再进行网页测试,重新测试通过。
,然后在控制器中添加对应的编辑,保存方法
/**
* 添加用户
*
* @param model
* @return
*/
@RequestMapping("/add")
public void add(Model model) {
try {
// 与form绑定的模型
model.addAttribute("user", new User());
// 用于生成“性别”下拉列表
model.addAttribute("sexList", dictService.getDictByField("SEX"));
// 用于生成“学历”下拉列表
model.addAttribute("eduList", dictService.getDictByField("EDU"));
LOGGER.info("查询用户性别,学历信息列表");
} catch (Exception e) {
// TODO: handle exception
LOGGER.info("查询用户性别,学历信息列表," + e.getMessage());
model.addAttribute("success", false);
model.addAttribute("errorMsg", "查询性别,学历列表失败");
}
}
/**
* 添加用户保存
*
* @param model
* @param entity
* @param bindingResult
* @return
*/
@RequestMapping("/addSave")
public String addSave(Model model,@ModelAttribute("user") @Valid User user,BindingResult bindingResult) {
try {
// 如果模型中存在错误
if (!bindingResult.hasErrors()) {
if (userService.insertUser(user) > 0) {
return "redirect:/user/list";
}
}
model.addAttribute("user", user);
// 用于生成“性别”下拉列表
model.addAttribute("sexList", dictService.getDictByField("SEX"));
// 用于生成“学历”下拉列表
model.addAttribute("eduList", dictService.getDictByField("EDU"));
return "";
} catch (Exception e) {
// TODO: handle exception
return "user/add";
}
}
这里有一个问题是因为使用了JSR303校验,当保存对象是需要在参数前注解@ModelAttribute("entity") @Valid,用于激活校验,否则页面将不会有错误展示。
为了配合Bean Validation,定义的User Bean需要注解,内容如下:
public class User {
private Integer userId;
@NotEmpty(message="{用户名称不能为空}")
private String userName;
@NotEmpty(message="{用户性别不能为空}")
private String userSex;
@NotEmpty(message="{用户出生日期不能为空}")
private Date userBirthday;
@NotEmpty(message="{用户邮箱不能为空}")
private String userEmail;
@NotEmpty(message="{用户学历不能为空}")
private String userEdu;
@NotEmpty(message="{用户电话号码不能为空}")
private String userTelephone;
添加对应的add.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<link href="<c:url value="/styles/main.css" />" type="text/css" rel="stylesheet" />
<script language="javascript" type="text/javascript"
src="<c:url value="/scripts/My97DatePicker/WdatePicker.js" />"></script>
<title>新增用户</title>
</head>
<body>
<div class="main">
<h2 class="title"><span>新增用户</span></h2>
<form:form action="addSave" method="post" modelAttribute="user">
<fieldset>
<legend>用户</legend>
<table cellpadding="5" cellspacing="8">
<tr>
<td><label for="userName">姓名:</label></td>
<td><form:input path="userName" size="40"/></td>
<td><form:errors path="userName" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><label for="userSex">性别:</label></td>
<td>
<form:select path="userSex" style="width:100%">
<form:option value="">--请选择--</form:option>
<form:options items="${sexList}" itemLabel="codedesc" itemValue="code"/>
</form:select>
</td>
<td><form:errors path="userSex" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><label for="userBirthday">出生日期:</label></td>
<td><form:input path="userBirthday" size="40" class="Wdate" onClick="WdatePicker()"/></td>
<td><form:errors path="userBirthday" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><label for="user_email">邮箱:</label></td>
<td><form:input path="userEmail" size="40"/></td>
<td><form:errors path="userEmail" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><label for="userEdu">学历:</label></td>
<td>
<form:select path="userEdu" style="width:100%">
<form:option value="">--请选择--</form:option>
<form:options items="${eduList}" itemLabel="codedesc" itemValue="code"/>
</form:select>
</td>
<td><form:errors path="userEdu" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><label for="userTelephone">联系方式:</label></td>
<td><form:input path="userTelephone" size="40"/></td>
<td><form:errors path="userTelephone" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><label for="userAddress">家庭住址:</label></td>
<td><form:input path="userAddress" size="40"/></td>
<td><form:errors path="userAddress" cssClass="error"></form:errors></td>
</tr>
</table>
<p>
<input type="submit" value="保存" class="btn out">
</p>
</fieldset>
<!--<form:errors path="*"></form:errors> -->
</form:form>
<p style="color: red">${message}</p>
<p>
<a href="<c:url value="/user/list" />" class="abtn out">返回列表</a>
</p>
</div>
</body>
</html>
完善编辑功能
/**
* 编辑用户
* @param model
* @param user_id
* @return
*/
@RequestMapping("/edit/{user_id}")
public String edit(Model model,@PathVariable int user_id){
try {
model.addAttribute("user", userService.queryUserById(user_id));
// 用于生成“性别”下拉列表
model.addAttribute("sexList",dictService.getDictByField("SEX"));
// 用于生成“学历”下拉列表
model.addAttribute("eduList",dictService.getDictByField("EDU"));
} catch (Exception e) {
// TODO: handle exception
}
return "user/edit";
}
/**
* 修改用户并保存
* @param model
* @param user
* @param bindingResult
* @return
*/
@RequestMapping("/editSave")
public String editSave(Model model,@ModelAttribute("user") @Valid User user,BindingResult bindingResult){
try {
//如果模型中存在错误
if(!bindingResult.hasErrors()){
if(userService.updateUser(user)>0)
{
return "redirect:list";
}
}
model.addAttribute("user", user);
model.addAttribute("sexList",dictService.getDictByField("SEX"));
model.addAttribute("eduList",dictService.getDictByField("EDU"));
} catch (Exception e) {
// TODO: handle exception
}
return "/user/edit";
}
添加对应的编辑页面。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<link href="<c:url value="/styles/main.css" />" type="text/css" rel="stylesheet" />
<script language="javascript" type="text/javascript"
src="<c:url value="/scripts/My97DatePicker/WdatePicker.js" />"></script>
<title>编辑用户</title>
<base href="<%=basePath %>" />
</head>
<body>
<div class="main">
<h2 class="title"><span>编辑用户</span></h2>
<form:form action="user/editSave" method="post" modelAttribute="user">
<fieldset>
<legend>用户</legend>
<table cellpadding="5" cellspacing="8">
<tr>
<td><label for="user_name">姓名:</label></td>
<td><form:input path="user_name" size="40"/></td>
<td><form:errors path="user_name" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><label for="user_sex">性别:</label></td>
<td>
<form:select path="user_sex" style="width:100%">
<form:option value="">--请选择--</form:option>
<form:options items="${sexList}" itemLabel="codedesc" itemValue="code"/>
</form:select>
</td>
<td><form:errors path="user_sex" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><label for="user_birthday">出生日期:</label></td>
<td><form:input path="user_birthday" size="40" class="Wdate" onClick="WdatePicker()"/></td>
<td><form:errors path="user_birthday" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><label for="user_email">邮箱:</label></td>
<td><form:input path="user_email" size="40"/></td>
<td><form:errors path="user_email" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><label for="user_edu">学历:</label></td>
<td>
<form:select path="user_edu" style="width:100%">
<form:option value="">--请选择--</form:option>
<form:options items="${eduList}" itemLabel="codedesc" itemValue="code"/>
</form:select>
</td>
<td><form:errors path="user_edu" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><label for="user_telephone">联系方式:</label></td>
<td><form:input path="user_telephone" size="40"/></td>
<td><form:errors path="user_telephone" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><label for="user_address">家庭住址:</label></td>
<td><form:input path="user_address" size="40"/></td>
<td><form:errors path="user_address" cssClass="error"></form:errors></td>
</tr>
</table>
<p>
<form:hidden path="user_id" />
<input type="submit" value="保存" class="btn out">
</p>
</fieldset>
<!--<form:errors path="*"></form:errors> -->
</form:form>
<p style="color: red">${message}</p>
<p>
<a href="<c:url value="/user/list" />" class="abtn out">返回列表</a>
</p>
</div>
</body>
</html>
添加删除用户代码
/**
* 根据用户id删除用户
* @param model
* @param user_id
* @param pageNO
* @param redirectAttributes
* @return
*/
@RequestMapping("/deleteUserById/{user_id}")
public String deleteUserById(Model model,@PathVariable int user_id,@RequestParam(required=false,defaultValue="1") int pageNO,
RedirectAttributes redirectAttributes){
if(userService.deleteUserById(user_id)>0){
redirectAttributes.addFlashAttribute("message", "删除成功!");
}else{
redirectAttributes.addFlashAttribute("message", "删除失败!");
}
return "redirect:/user/list?pageNO="+pageNO;
}
/**
* 删除多个用户
* @param model
* @param userIds
* @param pageNO
* @param redirectAttributes
* @return
*/
@RequestMapping("/deleteUsers")
public String deleteUsers(Model model,@RequestParam int[] user_id,@RequestParam(required=false,defaultValue="1") int pageNO,
RedirectAttributes redirectAttributes){
if(userService.deleteUsers(user_id)>0){
redirectAttributes.addFlashAttribute("message", "删除成功!");
}else{
redirectAttributes.addFlashAttribute("message", "删除失败!");
}
return "redirect:/user/list?pageNO="+pageNO;
}
OK,基础的代码完成了。