个人网站的页面上有一个留言功能,现在实现一下。
一、设计数据库
1.mysql数据库,新建boke库。
目前只有一张留言的数据表,比较简单。
CREATE TABLE `message` (
`id` varchar(32) NOT NULL COMMENT '主键',
`fullName` varchar(128) DEFAULT NULL COMMENT '用户姓名',
`phoneNumber` varchar(32) DEFAULT NULL COMMENT '电话',
`emailAddress` varchar(32) DEFAULT NULL COMMENT '邮箱',
`subject` varchar(256) DEFAULT NULL COMMENT '简要信息',
`message` varchar(1024) DEFAULT NULL COMMENT '留言信息',
`user_ip` varchar(128) DEFAULT NULL COMMENT '用户ip',
`create_user` varchar(32) DEFAULT NULL COMMENT '创建者',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`del_flag` int(1) DEFAULT '0' COMMENT '数据状态',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
二、工程配置
1.引入依赖包
<!--mybatis -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!--druid -->
<!--DRUID是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0、DBCP、PROXOOL等DB池的优点,同时加入了日志监控,-->
<!--可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池(据说是目前最好的连接池,不知道速度有没有BoneCP快)。-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.28</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
注:这里用到了阿里的数据库连接池。
2.application-dev.yml文件
我们为数据库连接专门写一个配置文件,命名为application-dev.yml。如下:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/boke?useUnicode=true&characterEncoding=utf8
username: root
password: 1234
initialSize: 1
minIdle: 3
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 30000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
3.在application.yml文件中增加数据库配置。
spring:
profiles:
active: dev
4.使用mabatis+generator插件生成相关代码。具体的操作步骤:
https://blog.csdn.net/weixin_42074377/article/details/80743529
5.设计一个RestUtil.java。用于返回信息。如下:
public class RestUtil {
private int status;
private String msg;
private Object data;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
@Override
public String toString() {
return "RestUtil{" +
"status=" + status +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
}
5.这里生成的代码还需要完善一下,自己编写MessageControlle、MessageService极其实现类。如下:
@RestController
@RequestMapping("/message")
public class MessageControlle {
@Autowired
private MessageService messageService;
@PostMapping("/insert")
public RestUtil insert(HttpServletRequest request, Message message) throws Exception{
RestUtil restUtil = new RestUtil();
String IP = IPUtil.getIpAddr(request);
message.setUserIp(IP);
if (messageService.insertSelective(message) > 0) {
restUtil.setMsg("我会尽快回复您的留言");
restUtil.setStatus(20000);
} else {
restUtil.setMsg("未知错误,请联系中边");
restUtil.setStatus(20001);
restUtil.setData(message);
}
return restUtil;
}
}
public interface MessageService {
int insertSelective(Message record);
}
@Service
public class MessageServiceImpl implements MessageService{
@Autowired
private MessageMapper messageMapper;
@Override
public int insertSelective(Message record) {
return messageMapper.insertSelective(record);
}
}
6.mapper.xml文件增加自增配置
<insert id="insertSelective" parameterType="com.byk.myboke.boke.entity.Message" >
<selectKey keyProperty="id" resultType="string" order="BEFORE">
select replace(uuid(), '-', '') as id from dual
</selectKey>
insert into message
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="fullname != null" >
fullName,
</if>
<if test="phonenumber != null" >
phoneNumber,
</if>
<if test="emailaddress != null" >
emailAddress,
</if>
<if test="subject != null" >
subject,
</if>
<if test="message != null" >
message,
</if>
<if test="userIp != null" >
user_ip,
</if>
<if test="createUser != null" >
create_user,
</if>
<if test="createTime != null" >
create_time,
</if>
<if test="delFlag != null" >
del_flag,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=VARCHAR},
</if>
<if test="fullname != null" >
#{fullname,jdbcType=VARCHAR},
</if>
<if test="phonenumber != null" >
#{phonenumber,jdbcType=VARCHAR},
</if>
<if test="emailaddress != null" >
#{emailaddress,jdbcType=VARCHAR},
</if>
<if test="subject != null" >
#{subject,jdbcType=VARCHAR},
</if>
<if test="message != null" >
#{message,jdbcType=VARCHAR},
</if>
<if test="userIp != null" >
#{userIp,jdbcType=VARCHAR},
</if>
<if test="createUser != null" >
#{createUser,jdbcType=VARCHAR},
</if>
<if test="createTime != null" >
#{createTime,jdbcType=TIMESTAMP},
</if>
<if test="delFlag != null" >
#{delFlag,jdbcType=INTEGER},
</if>
</trim>
</insert>
三、前端界面相关
1.index.heml文件修改
因为是留言功能,所以主要修改的是留言区域,我这里增加了一个电话号码的填写。
<fieldset id="contact_form">
<div id="msgs"> </div>
<form id="cform" name="cform" method="post" action="">
<input type="text" id="name" name="fullname" value="姓名*" onFocus="if(this.value == '姓名*') this.value = ''" οnblur="if(this.value == '') this.value = '姓名*'" />
<input type="text" id="email" name="emailaddress" value="邮箱*" onFocus="if(this.value == '邮箱*') this.value = ''" οnblur="if(this.value == '') this.value = '邮箱*'" />
<input type="text" id="phonenumber" name="phonenumber" value="手机号码*" onFocus="if(this.value == '手机号码*') this.value = ''" οnblur="if(this.value == '') this.value = '手机号码*'" />
<input type="text" id="subject" name="subject" value="摘要*" onFocus="if(this.value == '摘要*') this.value = ''" οnblur="if(this.value == '') this.value = '摘要*'" />
<textarea id="msg" name="message" value="正文(200字以内)*" onFocus="if(this.value == '正文(200字以内)*') this.value = ''" οnblur="if(this.value == '') this.value = '正文(200字以内)*'" MaxLength="400">正文(200字以内)*</textarea>
<button id="submit" class="button" > 留言</button>
</form>
</fieldset>
2.setup.js文件
- 手机号码校验
- 信息填写错误的提示
- 留言完成以后刷新页面
function checkPhone(phonenumber) {
var check = /^[1][2,3,4,5,6,7,8,9][0-9]{9}$/;
if (!check.test(phonenumber)) {
return false;
}
return true;
}
function sendMessage() {
// receive the provided data
var name = $("input#name").val();
var email = $("input#email").val();
var subject = $("input#subject").val();
var msg = $("textarea#msg").val();
var phonenumber =$("input#phonenumber").val();
// check if all the fields are filled
if (name == '' || name == '姓名*' || email == '' || email == '邮箱*'|| phonenumber == ''|| phonenumber == '手机号码*' || subject == '' || subject == '摘要*' || msg == '' || msg == '正文(200字以内)*') {
$("div#msgs").html('<p class="warning">请完整的填写您的信息</p>');
return false;
}
// verify the email address
if (!checkEmail(email)) {
$("div#msgs").html('<p class="warning">请填写正确的邮箱格式</p>');
return false;
}
if (!checkPhone(phonenumber)) {
$("div#msgs").html('<p class="warning">请填写正确的手机号码</p>');
return false;
}
// make the AJAX request
var dataString = $('#cform').serialize();
$.ajax({
type: "POST",
url: '/message/insert',
data: dataString,
dataType: 'json',
success: function (restUtil) {
if (restUtil.status == 20001) {
var errors = '<ul><li>';
if (data.message.fullname != '')
errors += data.message.fullname + '</li>';
if (data.message.emailaddress != '')
errors += '<li>' + data.message.emailaddress + '</li>';
if (data.message.phonenumber != '')
errors += '<li>' + data.message.phonenumber + '</li>';
if (data.message.subject != '')
errors += '<li>' + data.message.subject + '</li>';
if (data.message.message != '')
errors += '<li>' + data.message.message + '</li>';
$("div#msgs").html('<p class="error" >无法完成您的请求。请参阅下面的错误!</p>' + errors);
}
else if (restUtil.status == 20000) {
$("div#msgs").html('<p class="error" >留言已收到,我们会尽快回复您。</p>');
$('#cform').empty();
var str = '';
str += '<input type="text" id="name" name="fullname" value="Full Name*" onFocus="if(this.value == \'Full Name*\') this.value = \'\'" οnblur="if(this.value == \'\') this.value = \'Full Name*\'" />';
str += '<input type="text" id="email" name="emailaddress" value="Email Address*" onFocus="if(this.value == \'Email Address*\') this.value = \'\'" οnblur="if(this.value == \'\') this.value = \'Email Address*\'" />';
str += '<input type="text" id="phonenumber" name="phonenumber" value="Phone Number*" onFocus="if(this.value == \'Phone Number*\') this.value = \'\'" οnblur="if(this.value == \'\') this.value = \'Phone Number*\'" />';
str += '<input type="text" id="subject" name="subject" value="Subject*" onFocus="if(this.value == \'Subject*\') this.value = \'\'" οnblur="if(this.value == \'\') this.value = \'Subject*\'" />';
str += '<textarea id="msg" name="message" onFocus="if(this.value == \'200字以内\') this.value = \'\'" οnblur="if(this.value == \'\') this.value = \'200字以内\'" MaxLength="400">200字以内</textarea>';
str += '<button id="submit" class="button" οnclick="sendup();"> 留言</button>';
$('#cform').append(str);
}
},
error: function () {
$("div#msgs").html('<p class="error">未知错误,请联系中边!</p>');
}
});
return false;
}
四、功能测试
启动项目,浏览器进行访问。
查看数据库,信息已经写入。
如果页面信息填写不完善,会有相关的提醒。