长时间没有更新博客了,因为最近比较忙,一边在忙web开发框架的大作业,另一边还有一个PyQT5的项目需要完成.正好上周把这两个大山搞定了,总结一下做这两个项目的困难点,此篇先总结一下web开发框架(ssh).
这个项目后端才有struts2+spring+hibernate的框架,使用MySQL数据库,前端使用的是layUI模板.IDE是最新版的idea,我知道ssh几乎没人用的,但毕竟老师教的是这个,不管是应付期末考试还是提高自己能力(做了这个项目之后再用其它框架上手也快),我也认真学了.
第一个让我抓狂就是环境配置,把三个框架整合在一起.因为经常会报一些spring bean初始化错误,然后后面很长一串都是配置的各种bean的错误,这里我理解的最重要的点就是把直接看到一行的最后,往往都是参数配置错误或者jar缺失,参数配置错误就改参数,缺少jar包就加jar包,推荐大家去maven下载相应的jar包,首先比较齐全,其次比较正规.当然直接在项目中引入maven更好.如果还是看不出所以然,配置log4j日志显示,这个日志显示工具显示的很齐全可以定位到错误点,方便修改,这个日志查看文件非常方便,如果我早一点发现,估计我就能省不少debug时间,特别是后期和前端交互时,常规的控制台有些错误不会输出,但有了log4j可以清晰的看出问题.
另一点,在spring和struts2整合的时候,容易出现一些问题,大概就是配置完web.xml之后启动Tomcat时候报错,这个时候控制台的输出会显示错误的地方,很多情况下也是jar包缺少的问题,还是老规矩加jar包.
不过如果有能力的话,建议学习一个maven一个包管理工具,可以把所有需要的jar包以代码的形式引入。大大方便了项目构建,不需要一个一个的去下载jar包,在别的环境使用的时候,也无需自带jar包,全部通过maven的仓库引入。
建议别使用最新的版本,也别使用太老的版本,太新的容易出现兼容性问题。太老的,有的方法已经舍弃不使用了,有的解决方案也不兼容。
我的使用版本是
交互环境为了方便统一,我舍弃了struts2自带的值栈的形式,采用了更通用且灵活的ajax,数据传输的格式统一采用了json。struts2的值栈虽然很简单,但有时候比较死板,容易出现问题,采用Ajax一方面可以做到异步请求(此时异步和同步请求得到了统一),另一方面追踪问题也方便。
这个问题是新版本才有的,只需要配置好hibernate的事务切点就可以对数据库内容增删改了。
hibernate的对象之间的关联关系有很多种,比如一对一,一对多,多对多。而在面对不同的关联关系的时候hibernate有不同的表示和处理方法,一定不能弄错,不然你可能就会发现,为啥这个数据删除不了?为啥没法级联删除等等问题。
遇到这个问题的我很懵逼,比如
String hql = "from Doc where inboxId ='" + inboxId + "'";
此时一定要加这个单引号,不然就会查询不到。因为只有如果不加单引号,就会被认为是整型,而不是字符串类型。
之前一直用的是SimpleMailMessage,这个类只能发送简单的邮件格式,没法发送HTML格式的,改成MimeMessage即可。
需要先对传递过来的json字符串转成自己想要的数据,之后再存储下来。这里存储的时候需要弄清楚相对路径和绝对路径
这里强烈建议不要使用Java的Date类了,使用Java1.8开始支持的LocalDate,Date的很多用法比较反人类,而且再Java1.8的时候就提示过时了。
因为我使用的一些网上copy的代码使用的还是Date,改动起来实在是不方便,但是使用起来包括存储到数据库中实在是更不方便,因此我打算写一个工具类,专门实现Date和LocalDate之间的转换。
总的来说,LocalDate比Date强大太多了,有兴趣的可以自行学习一下。转化的代码如下。
public class DateTransform {
public static Object localDate2Date(Object object) {
if (object.getClass() == LocalDate.class) {
LocalDate localDate = (LocalDate) object;
ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
Instant instant1 = zonedDateTime.toInstant();
return Date.from(instant1);
}
if (object.getClass() == Date.class) {
Date date = (Date) object;
Instant instant = date.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
return zdt.toLocalDate();
}
return null;
}
}
其实后端还好,遇到的问题虽然多,但解决起来我多少也算有点经验。但前端我是真的没咋接触过,我们专业的学长学姐都学了前端,到了我们这一届老师觉得前端太简单,没必要开课程学,直接让我们自学了。我之前学习了一点HTML和CSS的知识,JavaScript是完全不会。所以前端的问题甚至比后端的还多。
这里我使用了layUI作为我的前端模板,据说layUI是最适合后端程序员使用的前端模板,感觉相对来说比较简单直观,稍微有点前端基础就可以掌握。
在学习使用layUI的时候,最常见的问题就是需要重新渲染。比如你在代码中用JavaScript动态更改了某个元素的属性,而此元素正好是layUI需要重新渲染的,你就需要加入xx.render()
,这样动态的改变属性才能生效,原因很简单,有些元素,不是你写的代码是啥样,它就是啥样,有的是你写完之后,layUI是新建了一个元素来实现你 想要的效果,你写的那个元素的代码不过是一个参照,当你动态更新的时候,你只是改变了你自己写的那个元素的属性,但和layUI新建的那一个没有变,因此你需要重新渲染。
Ajax说我是临时学的,学完之后用着用着就熟了。
问题大多数处在传递的数值data上,当传输整个表单的时候,需要先把表单序列化之后传输。序列化的方法也很简单,JavaScript自带有转成json字符串的方法,转一下就可以。
刚刚开始做前端部分的时候最让我头疼的就是前端的调试不像后端那样方便,特别像JavaScript这样的脚本语言,只有在运行的时候才能看到问题。不过还好有浏览器的开发者工具,经过这次大作业,我对其有了更深的理解。
这个看似容易的问题实在是难到我了,我实在是想不到有什么方法可以实现,但我感觉不是很难,查询一番资料也没有找到合适的答案,最后在问了一个大神的情况下告诉了我,用EL表达式。比如获取地址栏中参数为id的数值,${param.id}
。这个EL表达式是学JSP的时候知识点,但当时我们老师说这个不是考试重点,因为时间有限就不讲了,我也没当回事,后来发现有这用途。
在实际中,我遇到的问题远比上面提到的多,而且有的解决方案别看着简单,但对于当时的我来说就是一个个噩梦。但经过这一个大作业,我真切的感觉自己变强了。首先,项目也知道分层了,不再是一个文件,一把梭哈了。其次,逻辑思维更加严谨,能实现自己想要实现的功能,第三,debug能力有一个飞跃,之前debug模式我用的还不是很熟,经此一役,debug模式我玩的就很熟练了。第四,数据库的增删改查更清晰,虽然对于高级的属性掌握还一般,但至少基础的增删改查,我算是入门了。最后,我觉得最重要的还是前端能力,一个HTML和CSS都没学完,JavaScript更是一窍不通,在这么短的时间学会了很多。后面我继续学习前端的时候,明显感觉比较轻松了。
认真对待每一次大作业,真的能让人技术飞跃。