创建一个简单的springMVC+mybatis项目(三)
接着上一篇文章,我们已经完成springMVC+mybatis项目的登录功能,对相关知识也有了简单的了解,那么,helloworld就不再适合我们了,我们来尝试带有业务需求的去创建一个项目,在实战中完善对知识点的积累和学习,所以我们打算创建一个工程,用来统计所有同事的周报内容,并根据查询结果做excel导出。
首先我们来完成主体功能,最后在完善系统,接下来让我们一步步来
1、根据我们之前所学,先来创建一个工程,工程名叫wrmp(Work Record Manage Platform的缩写),我们之前没有用maven是为了让我们属实一下项目创建的基本需求,现在我们既然做实战项目,我们按实际情况来,使用maven来管理我们的jar包并构建项目。
我们使用的是sts,所以创建spring项目会和通常的eclipse有些不同,这里我只做sts的创建介绍,相信eclipse创建maven项目的流程肯定有很多大神已经分享过了,朋友们可以参考。
1)、下载maven的免安装包,解压到你电脑的指定空间作为maven的工作空间(我本就解压到C:\maven,创建E:\m2文件夹作为maven的本地仓库),配置maven配置文件(maven/conf/settings.xml)
因为我们自己开发学习,不是刻意学习maven,所以不用搭建maven私服,我们也就统一使用中央仓库(即maven的默认仓库),那我们就只需要在setting文件中配置下本地仓库地址就可以了,以后到了企业,肯定还要配置公司私服地址,具体配置可以单独学习
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <localRepository>E:/m2/repository</localRepository> </settings>
2)、maven准备好了,我们来配置下sts工作空间,使其使用我们刚刚准备好的maven管理我们这个工作空间所有项目的jar包
点击window->选择preference->搜索框输入maven->选择installations->点击add
点击Directory… 找到你的maven存放路径,点击finish
选中你刚添加进来的maven点击下面的ok按钮
点击user settings -> 点击Browse… 找到你的maven的setting.xml ->点击apply按钮->点击ok按钮完成sts工作空间maven的配置
3)、window->preferences-> general -> Workspace设置工作空间的编码格式为UTF-8
4)、右键-> new spring project如下图,选择spring mvc project -> next
填入你的包名,finish即可,你的项目创建成功了
然后你会发现你的项目报错,不用担心sts会自动帮我们构建项目并使用maven下载我们需要的包
然后我们的项目就创建完了,sts帮我们创建了一个springMVC项目,需要的文件和工程结构也都已经帮我们创建好了,看到一下的截图,你可能会发现,有个pom.xml是我们之前没有见过的,接下来我们就来看看这个pom.xml是做什么用的,不过这之前,老规矩,启动下项目,测试下是否能正常启动。
a-ok,我们成功了,下面我们来看下pom.xml
2、一个使用springMVC框架工程的基本骨架我们我们已经搭建好了,有的朋友可能要问,我们为什么没有需要引入相关的jar包呢?因为我们使用了maven呀,在构建sts的时候maven已经帮我们从我们配置的仓库(私服,这里我们没有配置,所以是走的默认的中央仓库)下载了我们需要的jar包并帮我们导入构建到了项目中。这时候你可能有想问了,可是maven怎么知道我们需要那些jar包已经需要什么版本呢?这就要看看我们刚才提到的pom.xml文件了。我们在pom中配置好我们需要jar包,在执行maven更新命令时,我们安装的maven插件就会去读取我们的pom文件,然后为我们下载我们需要的并配置在其中的jar包,下面我们来看看,一个springMVC+mybatis项目需要的jar包配置文件pom是啥样的:
<?xml version="1.0" encoding="UTF-8"?> <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> <!-- 默认基础包名,也是发布到maven私服时保存的路径名 --> <groupId>com.thc</groupId> <!-- 项目名 --> <artifactId>wrmp</artifactId> <name>wrmp</name> <!-- 当前项目在时候maven打包时,项目的打包后的文件类型 一般java项目打包类型是jar或是war,我们web项目都是打war包,即wrmp.war --> <packaging>war</packaging> <!-- 当前开发项目的版本 --> <version>1.0.0-BUILD-SNAPSHOT</version> <properties> <java-version>1.6</java-version> <org.springframework-version>3.1.1.RELEASE</org.springframework-version> <org.aspectj-version>1.6.10</org.aspectj-version> <org.slf4j-version>1.6.6</org.slf4j-version> <!-- 指明编译源代码时使用的字符编码,maven编译的时候默认使用的GBK编码, 通过project.build.sourceEncoding属性设置字符编码,告诉maven这个项目使用UTF-8来编译 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- Spring 项目使用的基本包 start --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework-version}</version> <exclusions> <!-- 排除 spring-context包中引用的的 commons-logging包 --> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework-version}</version> </dependency> <!-- Spring 项目使用的基本包 end --> <!-- AspectJ --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${org.aspectj-version}</version> </dependency> <!-- Logging日志包 start --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${org.slf4j-version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${org.slf4j-version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${org.slf4j-version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.15</version> <exclusions> <exclusion> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> </exclusion> <exclusion> <groupId>javax.jms</groupId> <artifactId>jms</artifactId> </exclusion> <exclusion> <groupId>com.sun.jdmk</groupId> <artifactId>jmxtools</artifactId> </exclusion> <exclusion> <groupId>com.sun.jmx</groupId> <artifactId>jmxri</artifactId> </exclusion> </exclusions> <scope>runtime</scope> </dependency> <!-- Logging日志包 end --> <!-- @Inject --> <dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency> <!-- web项目中的Servlet包 start --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- web项目中的Servlet包 end --> <!-- Test 单元测试 start --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> <scope>test</scope> </dependency> <!-- Test 单元测试 end --> <!-- mybatis需要的包 start --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.6</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.2</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp --> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.18</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>3.1.1.RELEASE</version> <exclusions> <exclusion> <artifactId>spring-beans</artifactId> <groupId>org.springframework</groupId> </exclusion> </exclusions> </dependency> <!-- mybatis需要的包 end --> <!-- spring requestbody 转换request中的表单内容使用 start --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.5</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.5</version> </dependency> <!-- spring requestbody 转换request中的表单内容使用 end --> </dependencies> <build> <plugins> <plugin> <artifactId>maven-eclipse-plugin</artifactId> <version>2.9</version> <configuration> <additionalProjectnatures> <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature> </additionalProjectnatures> <additionalBuildcommands> <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand> </additionalBuildcommands> <downloadSources>true</downloadSources> <downloadJavadocs>true</downloadJavadocs> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.5.1</version> <configuration> <source>1.6</source> <target>1.6</target> <compilerArgument>-Xlint:all</compilerArgument> <showWarnings>true</showWarnings> <showDeprecation>true</showDeprecation> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <configuration> <mainClass>org.test.int1.Main</mainClass> </configuration> </plugin> </plugins> </build> </project>
修改完pom文件后,不要忘记选中项目右键-> maven -> update project 更新jar包
3、现在我们该准备的东西都已经准备好了,可以开始写代码了,延续上一篇文章,我们要创建一个数据库来为我们的工程做数据持久化操作,同时创建我们需要的表,并使用mybatis反向工程生成我们的model层代码。
1)、我们创建一个名为wrmp的数据库,创建一下几张表:
CREATE TABLE `td_user` ( `user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id', `user_name` varchar(20) DEFAULT NULL COMMENT '用户名', `email` varchar(30) DEFAULT NULL COMMENT '用户邮箱', `mobile` varchar(20) DEFAULT NULL COMMENT '联系方式', `address` datetime DEFAULT NULL COMMENT '地址', `status` varchar(5) DEFAULT NULL COMMENT '用户状态:1可用,2注销', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `CREATE_id` int(11) NOT NULL COMMENT '创建人id', `update_time` datetime DEFAULT NULL COMMENT '修改时间', `update_id` int(11) NOT NULL COMMENT '修改人id', PRIMARY KEY (`user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COMMENT='系统用户表'; CREATE TABLE `td_work_record` ( `record_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '记录id', `user_id` int(11) DEFAULT NULL COMMENT '执行人id', `task_detail` varchar(500) DEFAULT NULL COMMENT '工作明细', `plan_start_time` datetime DEFAULT NULL COMMENT '计划工作开始时间', `plan_end_time` datetime DEFAULT NULL COMMENT '计划工作结束时间', `work_cost_time` int(3) DEFAULT NULL COMMENT '工时(天)', `work_status` varchar(5) DEFAULT NULL COMMENT '工作状态:1未开始,2进行中,3已完成', `part_of_project` varchar(30) DEFAULT NULL COMMENT '工作所属项目', `leave_remark` varchar(100) DEFAULT NULL COMMENT '请假备注', `overtime_remark` varchar(100) DEFAULT NULL COMMENT '加班备注', `record_type` varchar(5) DEFAULT NULL COMMENT '记录类型:1工作计划,2工作总结', `record_status` varchar(5) DEFAULT NULL COMMENT '记录状态:1被创建,2被删除', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `create_id` int(11) NOT NULL COMMENT '创建人id', `update_time` datetime DEFAULT NULL COMMENT '修改时间', `update_id` int(11) NOT NULL COMMENT '修改人id', PRIMARY KEY (`record_id`) ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COMMENT='工作记录表';
2)、创建mybatis方向工程需要的文件和文件夹并添加mybatis需要的配置
有报错,选中项目,邮件build path-> configura bulid path -> Libraries ,发现他默认给我们配置的是jdk1.6,
选中jdk -> edit ->选择自己的jdk,然后apply ok
发现还是报错,点击报错类发现提示的是成员变量重复,原来是重复操作了mybatis的方向工程,产生了重复字段,删掉方向工程生成的类,重新执行反向工程,ok
3)、我们发现他的spring配置文件默认是给我们生成在webapp/WEB-INF下面了,我们把它移回我们的resources文件夹下,同时修改web.xml的对应位置
3、接下来我们来准备我们的控制层方法了
那首先我们要分析下我们都要向用户提供怎么的功能、展示什么内容?
1)、我们要完善系统基础功能:权限功能(登录、注册、退出登录)
2)、我们的目的是要给用户展示工作记录的内容并且运行用户对其进行增删改查等一系列操作(业务功能)
3)、实现系统权限控制功能
也就是说,在这里我们就要给系统分出小模块了,接下来,我们按照这个需求来完成每个功能点,
首先是第一个,登录注册功能。由于注册功能只是提交表单插入一条记录,这个过程我们后面会练习到,所以我们不做赘述,忽略这个功能,那么我们可以直接安装之前的文章来完成登录功能,接下来,我们直接讲解退出登录功能。添加退出登录功能我们只需要在loginController中添加exitLogin方法(方法实现如下:),退出成功后直接跳转到登录界面即可。
退出登录入口应该是在业务功能界面的右上角
接下来,我们来实现系统的第二部分:业务功能实现
我们来简述下业务功能的需求:我们要实现的功能是用户登录的情况下,对本人工作内容的添加、列表展示、删除、修改、更改类型、批量导入、导出到excel表格中以及管理员登录时可以操作全部成员工作记录等功能。
按照之前几篇文章学习到的知识,我们已经准备好了数据库连接层的代码,下面我们来写controller层和他的服务代码service包中的内容:
1)、创建一专门用来操作工作记录功能的WorkRecordservice接口,定义操作工作记录的基本方法供controller调用
package com.thc.wrmp.service; import javax.servlet.http.HttpServletRequest; import com.thc.wrmp.db.model.TdUser; import com.thc.wrmp.db.model.TdWorkRecord; import com.thc.wrmp.vo.Page; /** * @author thc * @E-mail 2353635701@qq.com * @date 2019年1月11日 下午4:23:53 * @Description 工作记录操作类接口 */ public interface WorkRecordService { /** * 工作记录的分页查询方法 * * @param recordType * 记录类型 * @param nowPageNum * 当前页数 * @param onePageNum * 一页显示的条数 * @param u * 登录用户 * @return 返回分页类 */ public Page<TdWorkRecord> getWorkRecordListPage(String recordType, Integer nowPageNum, Integer onePageNum, TdUser u); /** * 工作记录的插入方法 * * @param record * 插入记录的内容(页面返回的实体) * @param recordType * 插入的工作记录类型 * @param request * 用来获得登录用户 */ public void addRecord(TdWorkRecord record, String recordType, HttpServletRequest request); /** * 根据记录id删除内容 */ public void deleteRecord(int id); /** * 根据新的工作记录内容修改id对应的旧的工作内容 * * @param record */ public void updateRecord(TdWorkRecord record); /** * 修改工作记录个类型 * * @return */ public String changeWorkPlanToSummary(String recordType); }
2)、在controller包下创建一个控制类WorkRecordController(说到这里时我们有必要了解一下springmvc的注解详解了,分享文章:https://www.cnblogs.com/leskang/p/5445698.html)
package com.thc.wrmp.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import com.thc.wrmp.db.model.TdUser; import com.thc.wrmp.db.model.TdWorkRecord; import com.thc.wrmp.service.WorkRecordService; import com.thc.wrmp.utils.Dictionary; import com.thc.wrmp.utils.SessionHelper; import com.thc.wrmp.vo.Page; /** * @author thc * @E-mail 2353635701@qq.com * @date 2019年1月11日 下午4:21:55 * @Description 类描述 */ @Controller public class WorkRecordController { @Autowired private WorkRecordService wService; /** * 查询工作记录列表 * * @return */ @RequestMapping(value = "/recordList/{recordType}", method = RequestMethod.GET) public String getWorkRecordList(HttpServletRequest request, HttpServletResponse response, Model model, @RequestParam(defaultValue = "1", value = "nowPageNum", required = false) Integer nowPageNum, @RequestParam(defaultValue = Dictionary.ONE_PAGE_NUMBER + "", value = "onePageNum", required = false) Integer onePageNum, @PathVariable("recordType") String recordType) { TdUser u = SessionHelper.getLoginUser(request); Page<TdWorkRecord> page = wService.getWorkRecordListPage(recordType, nowPageNum, onePageNum, u); model.addAttribute("page", page); return "weekWork/" + Dictionary.RECORDTYPE.get(recordType); } @RequestMapping(value = "/addWorkRecord/{recordType}", method = RequestMethod.POST) public String addWorkRecord(HttpServletRequest request, Model model, @ModelAttribute("tdWorkRecord") TdWorkRecord tdWorkRecord, @PathVariable("recordType") String recordType) { wService.addRecord(tdWorkRecord, recordType, request); return "redirect:/recordList/" + recordType; } @RequestMapping(value = "/deleteWorkRecord/{recordType}", method = { RequestMethod.GET, RequestMethod.POST }) public String deleteWorkRecord(HttpServletRequest request, Model model, @RequestParam(value = "record_id", required = true) String id, @PathVariable("recordType") String recordType) { if (id != null && !"".equals(id)) { // 字符串转int wService.deleteRecord(Integer.parseInt(id)); } // 重定向到查询列表,返回最新工作记录内容 return "redirect:/recordList/" + recordType; } @RequestMapping(value = "/updateWorkRecord/{recordType}", method = RequestMethod.POST) public String updateWorkRecord(HttpServletRequest request, Model model, @ModelAttribute("tdWorkRecord") TdWorkRecord tdWorkRecord, @PathVariable("recordType") String recordType) { wService.updateRecord(tdWorkRecord); // 重定向到查询列表,返回最新工作记录内容 return "redirect:/recordList/" + recordType; } /** * 修改工作记录个类型 * * @return */ @RequestMapping(value = "/changeWorkPlanToSummary/{record_id}", method = { RequestMethod.GET, RequestMethod.POST }) public String changeWorkPlanToSummary(HttpServletRequest request, Model model) { wService.changeWorkPlanToSummary("1"); // 重定向到查询列表,返回最新工作记录内容 return "redirect:/recordList/1"; } }
3)、创建实现类WorkRecordServiceImpl实现接口WorkRecordService的方法(这里要了解一下mybatis的一种分页插件:RowBoundsPlugin)
4)、完成所需页面编写
启动程序,访问应用,登录成功后,我们发现,我们已经成功进入页面了,只是页面的样式没有加载出来,在浏览器界面点击F12,打开浏览器开发者模式,查看样式文件的路径,发现我们没有做对应的映射(web项目中,webapp下的文件都不能在浏览器中直接访问,必须通过java方法跳转,js和css文件也要通过配置spring的映射路径才能访问到。)
修改servlet-context.xml文件,添加如下代码:
<resources mapping="/resources/**" location="/resources/" />
再次启动应用,访问程序,发现页面正常显示,添加记录信息->提交,dubug程序,插入数据库成功
但奇怪的是:我们发现我们在页面输入中文,到了数据库保存后竟然成了乱码,这是因为我们servlet未处理中文乱码问题,后台接收到的中文就已经是乱码了,为了解决这个问题,我们只需要在web.xml中加入解决乱码的代码如下
<!-- 解决乱码 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>