发表于: 2018-04-25 13:22:21
0 675
今天完成的事情:
任务一总结
任务名称:JAVA-task1
成果连接:链接
任务耗时:共20天
技能脑图:
个人
官方脑图
任务总结:
虽然后面有点拖时间,但是任务进度基本符合预期
任务一刚开是做是一些软件的安装,数据库的属性,包括sql语法和maven规约,然后开始设计表的结果并用Jdbc尝试连接数据库,安装一些配置环境学习单元测试等,所有的这些在为第17步做准备,开始创建一个符合maven的工程写Dao接口,当我用jdbc实现了CURD的基本操作后,对连接数据库的流程在大脑中有了轮廓,后面开始学习jdbctemplate,是对jdbc的一种分装,简化了很多类似加载驱动开关连接的重复代码,因为这些都统一的交给了Spring容器来处理。后面进入正式的mybatis框架学习,mybatis虽然也是对jdbc的优化封装,但是感觉更加精简成熟,把sql语句配置在xml文件里即可,然后获取dao的代理对象就可以实现CRUD,这使我感觉很好奇大概了解了下动态代理是什么东西。
然后和Spring整合起来,然后是单元测试,改bug的过程中也是对知识点的更加明晰的巩固。最后用写好的整合的框架测试大强度的插入数据,开始让我了解到原来数据库也是有性能瓶颈的,也是需要优化的,而索引的使用也有它实在的道理,明白了索引的应用场景和不同索引的区别。从建表写sql到框架数据库压力测试,这一切从无到有让我体会到了整个持久层的构建过程。
任务一最大的难题就是就是那些配置Linux的时候,对这种纯命令行的模式有点陌生,那时候基本每天都留着一个没解决的问题失望而归,幸运的是第二天都能解决好。还有就是某些代码看不懂,慢慢随着理解的深入才好点。
总的来说,还是要多练习,多尝试,多思考。有很多的不足需要在下一任务中改进。
————————————————分割线———————————————————
任务二进展
task2-6 使用PostMan/dhc测试自己写的接口,确认接口可以正常使用。
发现这个软件确实很好用,可以做一些浏览器无法做的测试,我本来满足与自己的程序"能用"了,却没有考虑到它的健壮性在测试中发现了很多容易出bug的地方。通过大量的测试考虑到各种用户的奇葩输入,针对自己程序中的缺点进行完善,处理异常,制定异常的跳转页面。
主要体现在,对传进来的参数做判空处理,包括对于要操作的数据id看是否存在与数据库中,对不存在的情况做处理。
对于以上代码说两点:
1.如果发生了异常,将异常提示信息放到modle里,然后在专门处理异常的jsp中取出展现给用户。
2.针对于可能存在的用户直接访问网址的情况,比如更新操作,是要提交数据后页面自动携带数据跳转,如果用户直接访问这个网址,那是没有携带任何数据的。这种情况我着重处理更新与删除,因为查与增对于的get与post请求方式可以被jsp接收,直接跳转到相应jsp即可,而更新与删除对应的put的delete无法直接跳转到jsp页面,这时我用了重定向技术,但是要带参重定向的,因为不同的异常要有不同的页面展示信息,于是使用了带参数重定向,
如果用户的更新请求不是从列表页面调过来的,而是直接输入URL非法访问,是没有带任何数据的,判断到后做以下处理
对于不同的异常携带不同的参数重定向
//正式更新,向数据库发出请求
@RequestMapping(value = "/update", method = RequestMethod.PUT)
public String update(Model model, Person person) throws Exception{
logger.info("马上要执行更新了,我们先看下用户输入的信息:"+person);
if(person.getId()!=null){
int i = userService.updatePerson(person);
if(i==1) {
logger.info("--嘿,更新成功了哦--");
return "redirect:getAll";
}else{
model.addAttribute("message","没有插入成功 !");
return "failure";
}
}else {
//如果获得的id为空,说明用户不是从列表页面进来,而是直接访问
return "redirect:myerror?illegal=1";
}
//return "forward:getAll";}
//删除
@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
public String Delete(@PathVariable("id") Integer id, Model model) throws Exception{
int i = userService.deletePerson(id);
if(i==1){
logger.info("--嘿,删除成功了--");
}else {
return "redirect:../myerror?illegal=5";
//return "redirect:/taskUser/myerror?illegal=5"; 正确,
}
return "redirect:/taskUser/getAll";
}
//错误页面
@RequestMapping(value = "/myerror")
public String failure(Model model, Integer illegal) throws Exception{
logger.error("有操作发生了意外状况,请开发人员检测 !");
if (illegal==1) {
model.addAttribute("message", "请从列表页面进行修改(非法操作)");
}else if(illegal==5){
model.addAttribute("message", "您删除的数据不存在(非法操作)");
}
return "failure";
}
注意上面被标浅绿的参数,如果是更新是发生的,带参数illegal==1,如果是删除是发生的带参数illegal==5,然后重定向到处理方法/myerror路径,这个方法对参数做判断,从而向model中放入不同的数据以供前台显示。
演示:
比如当用户直接在URL输入以下网址,删除随意乱写的id值的数据
这时判断到后前台展示如下
如果更新请求是用户直接输入以下URL,这是不带任何数据的。由于我的更新是要从一个满载数据的jsp里跳过来的,如果直接访问势必发生异常。
后台判断到后,带参重定向,页面显示
关键是jsp不接受put和delet请求方式的访问,否则直接在转发即可,转发由于共享一个request,请求方式,一样,于是只能通过带参重定向的方式。
明天计划的事情:
明天开始任务二的深度思考部分。
遇到的问题:
暂无。
收获:
对程序做了健壮性处理,不仅能用,更抗暴力使用。
关于重定向时路径的一些细节
//删除
@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
public String Delete(@PathVariable("id") Integer id, Model model) throws Exception{
int i = userService.deletePerson(id);
if(i==1){
logger.info("--嘿,删除成功了--");
}else {
/*
* 注意下面的 ..代表返回上一级,
*
* 如果是 return "redirect:..myerror?illegal=5";
* 重定向的路径为该路径(/myerror)替换当前末尾路径(/{id})加上前面的路径,
* 为http://localhost:8080/taskUser/delete/myerror?illegal=5,这个路径显然是不存在的。
*
* 如果是 return "redirect:/myerror?illegal=5";
* 由于第一个是 / , 重定向的路径为将是http://localhost:8080/myerror?illegal=5,这个也是不对的
*
* 只有当return "redirect:../myerror?illegal=5",
* 先 .. 返回上一级(从 /{id} 返回到 /delete),在替换路径(/myerror替换/delete)
* 猜得到了正确路径http://localhost:8080/taskUser/myerror?illegal=5
*
*/
return "redirect:../myerror?illegal=5";
//return "redirect:/taskUser/myerror?illegal=5"; 正确,
}
/*
*"redirect:/getAll" 会重定向到http://localhost:8080/getAll 这个地址显然是错的
*"redirect:getAll" 这样会采取相对路径,重定向到http://localhost:8080/taskUser/getAll 这个才是正确的
* 注意两者区别。
* 如果没有redirect,直接return "xxx"; 会是转发,共享一个request。
* return "forward:getAll" 转发,浏览器地址栏路径不会变
*
* 注意:下面redirect后路径以 / 开头,代表路径从contextpath开始算。
* 这个项目中在tomcat容器运行会重定向到http://localhost:8080//taskUser/getAll,
* 在jetty容器会重定向到http://localhost:8080/Jetty/taskUser/getAll,
* 因为我jetty容器的contextpath为 /Jetty .
*/
return "redirect:/taskUser/getAll";
}
注释中已经说的很清楚了,
总结: . . /xx 代表返回上一级,/xxx 代表从contextpath开始的路径。
评论