转载请注明出处:
牵手生活--头条新闻:笔记是整理思路方式,分享是一个美德,牵手是我的生活方式
牵手生活--简书:笔记是整理思路方式,分享是一个美德,牵手是我的生活方式
项目效果
机器人聊天url
http://localhost:8080/InitTalkServlet.action

机器人聊天
自动回复指令维护url
http://localhost:8080/List.action

自动回复指令维护
app实现流程
- javaBean 创建于数据库中表对应的实体
- dao:实现表对应的增删改查,如MessageDAO是和message表相关的数据库操作
- service:负责调用对应的dao,并实现与数据库无关的业务逻辑操作。如MessageService调用MessageDAO实现增删改查,并负责一些数据类型转换。
- servlet:主要是通过调用对应的service,提供http方法方法,并处理web访问的格式(如UTF-8)与参数接收。
- DbHelper:提供访问数据库辅助。如单例模式DBJdbcHelper提供jdbc方式访问mysql数据库连接对象Connection;DBMybatisHelper(还没改为单例模式)提供mybatis访问数据库的会话SqlSession

app实现流程
用idea创建一个maven 的web项目MicroMessageMybatis
注:如果对idea创建Manven webapp不熟悉,可参见Spring MVC -Hello World(环境搭建)

app 目录结构1

image.png
下面介绍涉及知识
- Maven
- mybatis(数据库访问框架)
- jdbc
- EL表达式(不介绍)
- JSTL表达式
- javaBean
- Servlet
- js(不介绍)
- jquery(不介绍)
下面介绍涉及的工作步骤
- pom.xml
- 创建mybatis的辅助类DBMybatisHelper.java
- 创建jdbc的辅助类DBJdbcHelper.java
- 配置mybatis配置文件入口.xml文件与不同的mapper对应的.xml
- 配置日志系统log4j的log4j.properties配置文件
- 搭建单元测试框架(这里仅用于调试mybatis获取数据功能)
- 创建不同的javaBean(基本与数据库表一致,涉及到父子表,采用List<子表javaBean>方式定义属性:如 private List<CommandContent> contentList;//一条指令对应的自动回复内容列表
) - 创建与javaBean对应的DAO:处理数据库的相关操作
- 创建service : 调用DAO跟数据库交互,还有一些业务逻辑需要处理,一般用service一般与servlet对应,被servlet调用
- 创建不同的servlet:
- 在web.xml中注册servlet,并配置http访问路径
- 创建单元测试用例
配置pom.xml 用Maven方式导入到
- mysql(访问mysql数据库)
- servlet
- slf4j(日志系统,用于测试mybatis)
- mybatis(数据库访问框架)
- junit单元测试
- JSTL(这里没有采用Maven的方式配置,而是导入对应的jar包)

JSTL表达式的jar包
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<!--添加Servlet-->
<!--添加Servlet-->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0-b01</version>
<scope>provided</scope>
</dependency>
<!-- slf4j日志处理 应用 log4j 调试动态 SQL-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- 添加mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.2</version>
</dependency>
<!--添加log4j依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.5.6</version>
</dependency>
</dependencies>
Mybatis中OGNL表达式

Mybatis中OGNL表达式1

Mybatis中OGNL表达式2
Mybatis配置文件
- mybatis配置文件入口Configuration.xml(可以是其他文件名称哦)
-
mybatis范围数据库的sql语句与参数配置文件Command.xml;CommandContent.xml;Message.xml
mybatis的配置文件参考mybatis源码中的例子:
mybatis配置例子路径
mybatis-3-mybatis-3.4.6\src\test\java\org\apache\ibatis\submitted\complex_property
- Configuration.xml:用于配置数据库连接
- User.xml:用于配置对user表的增、删、改、查
注意点:如果xml中有&符合,需要用&转义如
<property name="url" value="jdbc:mysql://**.96.**.27:3306/auth?serverTimezone=UTC&useUnicode=true"/>
需要改为
<property name="url" value="jdbc:mysql://**.96.**.27:3306/auth?serverTimezone=UTC&useUnicode=true"/>
Mybatis配置文件--Configuration.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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="" value=""/>
</transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://**.96.**.27:3306/auth?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="你的密码"/>
</dataSource>
</environment>
</environments>
<!--mybatis范围数据库的sql语句与参数配置文件-->
<mappers>
<mapper resource="sqlMybatisMapping/Message.xml"/>
<mapper resource="sqlMybatisMapping/Command.xml"/>
<mapper resource="sqlMybatisMapping/CommandContent.xml"/>
</mappers>
</configuration>
Mybatis配置文件--Message.xml
Message.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="Message">
<resultMap type="com.younghare.micromessage.bean.Message" id="MessageResult">
<!--数据库主键使用id标签,否则使用result标签;jdbcType对应jdbc中的java.sqlMybatisMapping.Types下的类型-->
<!--<result column="password" jdbcType="VARCHAR" property="password.encrypted"/>-->
<id column="ID" jdbcType="INTEGER" property="id"/>
<result column="COMMAND" jdbcType="VARCHAR" property="command"/>
<result column="description" jdbcType="VARCHAR" property="description"/>
<result column="CONTENT" jdbcType="VARCHAR" property="content"/>
</resultMap>
<!--配置一个sql语句,让mybatis可以读到并执行
resultMap:对应java中的javabean:与数据库查询结果对应的
xml中&不能直接使用必须转& ":也不能直接使用必须用"进行转
参数配置使用OGNL表达式:"表示单引号
-->
<!--SELECT * FROM message WHERE id = #{id:INTEGER}-->
<select id="queryMessageList" parameterType="com.younghare.micromessage.bean.Message" resultMap="MessageResult">
SELECT ID,COMMAND,DESCRIPTION,CONTENT FROM message where 1=1
<if test="command !=null and !"".equals(command.trim())">
and COMMAND = #{command}</if>
<if test="description !=null and !"".equals(description.trim())">
and DESCRIPTION like '%' #{description} '%' </if>
</select>
<!--单条记录删除-->
<delete id="deleteOne" parameterType="int">
DELETE FROM message WHERE ID = #{_parameterType}
</delete>
<!--批量记录删除,separator 是分隔符-->
<delete id="deleteBatch" parameterType="java.util.List">
DELETE FROM message WHERE ID in (
<foreach collection="list" item="item" separator=",">
#{item}
</foreach>
)
</delete>
</mapper>
Mybatis配置文件--父子表Command.xml、CommandContent.xml
Command.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="Command">
<!--
表返回数据与javaBean的映射关系;涉及到一对多关系
-->
<resultMap type="com.younghare.micromessage.bean.Command" id="Command">
<!--数据库主键使用id标签,否则使用result标签;jdbcType对应jdbc中的java.sqlMybatisMapping.Types下的类型
collection标签表示主表包含子表的一个集合与javaBean中的Command的CommandContent.Content属性对应;CommandContent的配置信息在CommandContent.xml中
C_ID 是查询中ID的别名
-->
<!--<result column="password" jdbcType="VARCHAR" property="password.encrypted"/>-->
<id column="C_ID" jdbcType="INTEGER" property="id"/>
<result column="NAME" jdbcType="VARCHAR" property="name"/>
<result column="DESCRIPTION" jdbcType="VARCHAR" property="description"/>
<collection property="contentList" resultMap="CommandContent.Content"/>
</resultMap>
<!--配置一个sql语句,让mybatis可以读到并执行
resultMap:对应java中的javabean:与数据库查询结果对应的
xml中&不能直接使用必须转& ":也不能直接使用必须用"进行转
参数配置使用OGNL表达式:"表示单引号
查询参数使Command实体对象,自动映射对象的属性作为参数如:command.name
left join 表示无论字表是否有内容,主表的内容必须出来
-->
<select id="queryCommandList" parameterType="com.younghare.micromessage.bean.Command" resultMap="Command">
select a.ID C_ID,a.NAME,a.DESCRIPTION,b.ID,b.CONTENT,b.COMMAND_ID
from COMMAND a left join COMMAND_CONTENT b
on a.ID=b.COMMAND_ID
<where>
<if test="name != null and !"".equals(name.trim())">
and a.NAME=#{name}
</if>
<if test="description != null and !"".equals(description.trim())">
and a.DESCRIPTION like '%' #{description} '%'
</if>
</where>
</select>
</mapper>
CommandContent.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="CommandContent">
<resultMap type="com.younghare.micromessage.bean.CommandContent" id="Content">
<id column="ID" jdbcType="INTEGER" property="id"/>
<result column="CONTENT" jdbcType="VARCHAR" property="content"/>
<result column="COMMAND_ID" jdbcType="VARCHAR" property="commandId"/>
</resultMap>
</mapper>
Mybatis配置文件的读取DBMybatisHelper.sql
public class DBMybatisHelper {
/**
* 根据配置文件返回一个mybatis的sqlsession
* @return
* @throws IOException
*/
public SqlSession getSqlSession() throws IOException {
//通过配置文件获取数据库连接信息,从src的目录开始
//Reader reader= Resources.getResourceAsReader("com/younghare/micromessage/config/Configuration.xml");
Reader reader= Resources.getResourceAsReader("Configuration.xml");
//通过配置信息构建一个SqlSessionFactory
SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(reader);
//通过sqlSessionFactory打开一个数据库会话
SqlSession sqlSession = sqlSessionFactory.openSession();
return sqlSession;
};
}
配置日志系统log4j配置(用于通过日志观察mybatis的sql语句、传递参数)
可以匹配值输出到控制台,也可以log输出到文件

控制台观察日志
log4j.properties
#配置输出到控制台,如果要输出到文件,需要修改这类
log4j.appender.Cons=org.apache.log4j.ConsoleAppender
# 按自己的想法输出
log4j.appender.Cons.layout=org.apache.log4j.PatternLayout
# 自定义输出日志的格式%d:产生日志的时间;%t:产生日志线程的线程名称;%5p:输出日志的级别(5位字符);%c:表示所处类的全名包括包名;%m:日志内容 %n:表示换行
log4j.appender.Cons.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
# Root logger set to DEBUG、Console using the A2 appender defined above.
#设置log4j输出日志的级别、位置DEBUG、Console
log4j.rootLogger=DEBUG, Cons
log4j.additivity=false
#key=value的形式进行配置
# 位某个包下配置不同的级别
log4j.logger.com.younghare.micromessage=debug, Cons
log4j.logger.org.springframework=debug, Cons
log4j.additivity.com=false
# 这个包下的输出的是NNFO日志级别
log4j.logger.org.apache=INFO
jdbc 访问mysql辅助类DBJdbcHelper.java
package com.younghare.micromessage.db;
import java.sql.Connection;
import java.sql.DriverManager;
public class DBJdbcHelper {
private static final String driver = "com.mysql.jdbc.Driver"; //数据库驱动
//连接数据库的URL地址
//private static final String url="jdbc:mysql://localhost:3306/phpmyadmin?useUnicode=true&characterEncoding=UTF-8";
private static final String url="jdbc:mysql://47.96.6.27:3306/auth?useUnicode=true&characterEncoding=UTF-8";
private static final String username="root";//数据库的用户名
private static final String password="emailczg";//数据库的密码
private static Connection conn=null;
//静态代码块负责加载驱动
static
{
try
{
Class.forName(driver);
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
//单例模式返回数据库连接对象
public static Connection getConnection() throws Exception
{
if(conn==null)
{
conn = DriverManager.getConnection(url, username, password);
return conn;
}
return conn;
}
public static void main(String[] args) {
try
{
Connection conn = DBJdbcHelper.getConnection();
if(conn!=null)
{
System.out.println("数据库连接正常!");
}
else
{
System.out.println("数据库连接异常!");
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
javaBean的创建(仅提供Message.java其他不列出来)
Message.java
/**
* 与指令消息表对应的实体类
*/
public class Message {
private String id; //主键
private String command; //指令名称
private String description; //描述
private String content; //内容
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
DAO的创建(仅提供MessageDAO.java其他不列出来)
MessageDAO.java
public class MessageDAO {
static Logger logger = LoggerFactory.getLogger(MessageDAO.class);; //LogDemo为相关的类
/**
* 查询消息列表
* @param command 指令
* @param description 描述 --模糊匹配
* @return 返回消息列表
*/
public List<Message> queryMessageListByMysql(String command,String description) {
List<Message> messageList = new ArrayList<>();
try {
Connection conn =DBJdbcHelper.getConnection();
//conn = DriverManager.getConnection(url, username, password);
String sqlQuery = "SELECT ID,COMMAND,DESCRIPTION,CONTENT FROM message where 1=1";
StringBuilder sql = new StringBuilder(sqlQuery);
List<String> paramList = new ArrayList<String>();
if (command != null && !"".equals(command.trim())){
sql.append(" and COMMAND = ?");
paramList.add(command);
}
if (description != null && !"".equals(description.trim())){
sql.append(" and DESCRIPTION like '%?%'");//模糊匹配
paramList.add(description);
}
System.out.println("sqlMybatisMapping:"+sql.toString());
PreparedStatement statement = conn.prepareStatement(sql.toString());
for(int i=0;i<paramList.size();i++){
statement.setString(i+1,paramList.get(i));
System.out.println(paramList.get(i));
}
ResultSet rs = statement.executeQuery();
while (rs.next()){
Message message = new Message();
messageList.add(message);
message.setId(rs.getString("ID"));
message.setCommand(rs.getString("COMMAND"));
message.setDescription(rs.getString("DESCRIPTION"));
message.setContent(rs.getString("CONTENT"));
}
//req.setAttribute("messageList",messageList);
}catch (ClassNotFoundException e){
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return messageList;
}
public List<Message> queryMessageList(String command,String description) {
List<Message> messageList = new ArrayList<>();
DBMybatisHelper dbMybatisHelper = new DBMybatisHelper();
SqlSession sqlSession = null;
try {
sqlSession = dbMybatisHelper.getSqlSession();
Message message = new Message();
message.setCommand(command);
message.setDescription(description);
//通过sqlSession执行SQL语句---Message:mapper namespace="Message";queryMessageList是在Message.xml配置的id
//messageList = sqlSession.selectList("Message.queryMessageList");//
messageList = sqlSession.selectList("Message.queryMessageList",message);//
} catch (IOException e) {
e.printStackTrace();
}finally {
if (sqlSession != null){
sqlSession.close();
}
}
return messageList;
}
/**
* 删除message中的一条记录
* @param id
*/
public void deleteOne(int id){
DBMybatisHelper dbMybatisHelper = new DBMybatisHelper();
SqlSession sqlSession = null;
try {
sqlSession = dbMybatisHelper.getSqlSession();
/*Message.deleteOne是:Message.xml配置的id*/
sqlSession.delete("Message.deleteOne",id);//
sqlSession.commit();//增删改都需要commit
} catch (IOException e) {
e.printStackTrace();
}finally {
if (sqlSession != null){
sqlSession.close();
}
}
}
/**
* 删除批量message中的记录
* @param ids
*/
public void deleteBatch(List<Integer> ids){
DBMybatisHelper dbMybatisHelper = new DBMybatisHelper();
SqlSession sqlSession = null;
try {
sqlSession = dbMybatisHelper.getSqlSession();
/*Message.deleteOne是:Message.xml配置的id*/
sqlSession.delete("Message.deleteBatch",ids);//
sqlSession.commit();//增删改都需要commit
} catch (IOException e) {
e.printStackTrace();
}finally {
if (sqlSession != null){
sqlSession.close();
}
}
}
}
service的创建(仅提供MessageService.java其他不列出来)
MessageService.java
/**
* 与ListServlet对应
* 跟数据库交互之前,还有一些业务逻辑需要处理,一般用service一般与servlet对应,被servlet调用
*/
public class MessageService {
/**
* 查询message的记录集合
* @param command
* @param description
* @return
*/
public List<Message> queryMessageList(String command,String description){
MessageDAO messageDAO = new MessageDAO();
return messageDAO.queryMessageList(command,description);
}
/**
* 删除message的某条记录
* @param id
*/
public void deleteOne(String id){
if (id != null && !"".equals(id.trim())){
MessageDAO messageDAO = new MessageDAO();
messageDAO.deleteOne(Integer.valueOf(id));
}
}
/**
* 删除message的某条记录
* @param ids
*/
public void deleteBatch(String[] ids){
List<Integer> idList = new ArrayList<Integer>();
for (String id : ids) {
idList.add(Integer.valueOf(id));
}
MessageDAO messageDAO = new MessageDAO();
messageDAO.deleteBatch(idList);
}
}
创建不同的servlet((仅提供ListServlet.java;DeleteOneServlet.java其他不列出来)
ListServlet.java
public class ListServlet extends javax.servlet.http.HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
doGet(request,response);
}
protected void doGet(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)
throws javax.servlet.ServletException, IOException {
//设置编码
req.setCharacterEncoding("UTF-8");
//接受页面的值
String command =req.getParameter("command");
String description = req.getParameter("description");
//向页面传值
req.setAttribute("command",command);
req.setAttribute("description",description);
//查询消息列表,并传递给页面
MessageService messageService = new MessageService();
req.setAttribute("messageList", messageService.queryMessageList(command,description));
//调整页面
req.getRequestDispatcher("/WEB-INF/jsp/back/list.jsp").forward(req,resp);
}
}
DeleteOneServlet.java
package com.younghare.micromessage.servlet;
import com.younghare.micromessage.service.MessageService;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import java.io.IOException;
/**
* message单条记录删除控制层
*/
@WebServlet(name = "DeleteOneServlet")
public class DeleteOneServlet extends HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
doGet(request,response);
}
protected void doGet(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)
throws javax.servlet.ServletException, IOException {
//设置编码
req.setCharacterEncoding("UTF-8");
//接受页面的值
String id =req.getParameter("id");
//查询消息列表,并传递给页面
MessageService messageService = new MessageService();
messageService.deleteOne(id);
//调整页面
req.getRequestDispatcher("/List.action").forward(req,resp);
}
}
在web.xml中注册servlet,并配置http访问路径
<web-app>
...
<servlet>
<servlet-name>ListServlet</servlet-name>
<servlet-class>com.younghare.micromessage.servlet.ListServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>DeleteOneServlet</servlet-name>
<servlet-class>com.younghare.micromessage.servlet.DeleteOneServlet</servlet-class>
</servlet>
...
<!--http://localhost:8080/List.action-->
<servlet-mapping>
<servlet-name>ListServlet</servlet-name>
<url-pattern>/List.action</url-pattern>
</servlet-mapping>
<!--http://localhost:8080/DeleteOneServlet.action-->
<servlet-mapping>
<servlet-name>DeleteOneServlet</servlet-name>
<url-pattern>/DeleteOneServlet.action</url-pattern>
</servlet-mapping>
...
</web-app>
创建单元测试用例MessageDAOTest
MessageDAOTest.java
import com.younghare.micromessage.bean.Message;
import org.junit.Test;
import java.util.List;
public class MessageDAOTest {
@Test
public void testqueryMessageList() {
MessageDAO messageDAO = new MessageDAO();
List<Message> messages = messageDAO.queryMessageList("","精");
System.out.println("记录数:"+messages.size());
}
@Test
public void testqueryMessageListByMysql() {
MessageDAO messageDAO = new MessageDAO();
List<Message> messages = messageDAO.queryMessageListByMysql("","");
System.out.println("记录数:"+messages.size());
}
}
