实习
继续努力吧,毕竟你在经历别人没有的经历。 –RuiDer
这篇文章来源于实习,本人外出实习,正值大二的自己还有些懵懂,找到实习公司格外欣喜。公司安排的第一个项目是一个公司内部考试系统,系统的功能包括管理员通过权限创建试卷,发布试卷,查看试卷,编辑试卷,删除试卷,批阅试卷,以及对于考生的选择等等。对于公司内部人员可以实时在公司内部系统中进行试卷阅读,完成考核,提交试卷,及时查看试卷成绩等功能。初次做功能相对复杂的系统,心理还是有点压力的。在这期间遇到几点问题,想和大家分享一下,也是我自己的总结吧。
文章目录
开发流程学习
很简单的流程,但是相对刚开始做项目的同学来说还是很新颖的
客户需求 ---> 需求文档的制作(有相关人员专门负责) ---> 项目开发设计文档(这个非常重要,因为后面的开发过程都是依据它的,无论前端还是后端,都要依靠它,相当于一个媒介) ---> 项目开发接口文档制作(前后端开发交流使用,包括数据传输,访问地址定义等等) ---> 最后才是敲代码(跟着流程速度才会提升)
学习制作项目开发设计文档
开发设计文档的要素有很多,说几个最重要的
一.项目介绍
二.关键功能
三.核心算法(核心逻辑)
www:who+where+what+数据落地
采用www方式即谁在哪做了什么把数据放到哪了这样的方式去描述各个模块
四.数据库
4.1 说明
说明数据库的作用等等
4.2 数据库的列表
4.2.1每个数据库表的说明
4.2.2数据库表列表
五.接口设计
包括接口地址,前后端数据的传输方式,传输参数(字段),类型,备注的说明以及返回数据的方式定义
具体学习
一.字符串和日期的转换:
字符串 ---> 日期
SimpleDataFormat sdf=new SimpleDataFormat("yyyy-MM-dd HH:mm:ss");
Date date=sdf.parse(str);
日期 ---> 字符串
SimpleDataFormat sdf=new SimpleDataFormat("yyyy-MM-dd HH:mm:ss");
String str=sdf.format(date);
注意bug:
yyyy-MM-dd HH:mm:ss 要和对应的时间一一对应,另外注意HH:mm中间是: 大小写也要注意
二.前端数据的处理
- 前端传递String字符串,如果是float数据,避免强转,比如:
float score=(float)map.get("score");这种做法是错的
可以使用:
float score=Float.valueOf(map.get("score").toString());
- 前端传输数据为JSONObject或者JSONArray时与Map、List之间的转换
推荐博文
三.强转费时
强转费时,例如:
String str=(String)map.get("score");
与
String str=(map.get("score")).toString();
四.Mybatis向数据库insert获取insert后的id
使用Mybatis向数据库insert,要想获取insert后的id,方法如下:
在Mybatis下的mapper文件中:
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert into user(Name,Age) values(#{user.name},#{user.age});
</insert>
这样操作之后在项目中要注意获取插入返回的id方法:
User user=new User();
user.setName("a");
user.setAge(10);
int x=userDao.add(user);
int userId=user.getId(); //注意这句userId!=x两者不相同
注意:
上述中的x可能等于1,也有可能等于0。1代表插入成功,0代表插入失败,如果插入了多行,则返回插入的行数,插入两行,返回2;插入三行,返回3;插入n行,返回n
五.线上测试
使用xshell进行线上测试,在测试环境下测试。(线上测试意思就是
项目发布到公司的服务器上后的调试方式)
步骤如下:
1.找到项目的log配置文件,一般式logback.xml
2.查看日志的保存路径
3.使用xshell或者在Linux系统下找到日志的保存路径
4.使用tail -nf [日志文件名]进行日志的查看,这里的n代表
行数,可以是任意一个数。
常用命令:
1.查看日志:tail -nf [日志文件名]
2.查看进程:ps -ef|grep [项目名称]
3.查看某个项目的堆情况:jmap -heap [进程id]
4.查看堆的占用情况:jamp -histo [进程id] | head -10 被哪些类占用了
5.查看栈的情况,是否死锁:jstack -m [进程id] | head -10
6.查看GC的情况:jstat -gcutil [进程id] n (n代表开始循环获取gc的次数)
7.查看某个进程启动的参数:jinfo -flag [进程id]
8.杀死进程:kill -9 [进程id]
六.bug的原因
在项目中找不到bug的原因时,找找看,继承接口的类中中有没有在方法的头部加上@Override ,这些低级错误会导致项目的进程中断
七.String类的方法:
7.1 subString(b,e); b从0开始,包含0,e代表结尾,不包含这个角标
7.2 是否包含某个字符contains(char a)
十一.500报错
500报错很有可能是后台代码错误!!
十一.代码规范习惯
代码规范习惯:
11.1 service层方法 读使用query,get,find开头
11.2 service层方法 写使用update,delete开头、
11.3 任何代码,具体说是Controller,Service层等类中勤于说明类或者方法的作用,参数是什么等等,养成好习惯。
十二.字符"|"的字符串spilit方法
包含字符"|"的字符串不要使用spilit方法,会出错。比如
String[] s="20|20".spilit("|");
for(int i=0;i<s.length;i++){
System.out.println(s[i]);
}
//输出结果:
2
0
|
2
0
到这里才结束,中间的这两个空格也是打印出来的。可想,这个符号不好用,最 好不要用。
解决方案:
1.修改符号
2.替换符号
- 两个方法的区别在于如果一个系统在测试时,首先插入到数据库时使用到这个符号,那么将导致所有插入的数据在数据库中将全部包含这个符号,在客户端查看数据时,需要使用spilit方法分离该字符串,就会出错!!这时候可以用最笨的方法,就是一个一个数据去找,然后修改这个符号,这种方法可行度不好。
- 替换符号的意思就是在客户端需要数据库的数据时,在后端程序中做出判断,如果字符串包含"|",先用其他符号,例如","," "等符号替换它,再做字符串分离,也就是使用spilit方法。
十二.SVN:
SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS、CVS,它采用了分支管理系统,它的设计目标就是取代CVS。互联网上很多版本控制服务已从CVS迁移到Subversion。说得简单一点SVN就是用于多个人共同开发同一个项目,共用资源的目的。
十三.前后端使用HashMap和List
注意使用HashMap和List的时候,在遇到循环的话尽量把HashMap放在循环里面去new,不然会遇到很大的问题。
比如:
1.
List<HashMap<String,Object>> list=new ArrayList<HashMap<String,Object>>();
HashMap<String,Object> map=new HashMap<String,Object>();
for(int i=0;i<10;i++){
map.put("a",i);
list.add(map);
}
2.
List<HashMap<String,Object>> list=new ArrayList<HashMap<String,Object>>();
for(int i=0;i<11;i++){
HashMap<String,Object> map=new HashMap<String,Object>();
map.put("a",i);
list.add(map);
}
这两段代码的区别在于map的为止不同,两段代码的输出结果分别是:
1.list:[{a:10},{a:10}...{a:10},{a:10}]
2.list: [{a:0},{a:1}...{a:8},{a:9},{a:10}]
区别很明显,这种错误在前后端传输数据时尤为重要,这段代码是我亲自使用前后端工具调试的。。
十四.前端调试工具
前端调试工具的熟练使用,有助于项目的跟近。
chorme:F12打开调试工具
一般后端开发人员需要注意就是Network,这里可以看到前后端交互的数据,交互方式(POST/GET),以及
请求的url,很方便
十五.项目增改操作
一个项目脱离不了增删改查,但是呢,在这次实习项目中,我了解到在开发中很多开发人员将增和改两个功能放在业务处理service的一个方法中,具体实现是这样的,增和改的区别在于增操作建立在空白场景下,前端只需要传输数据即可,空白场景的意思是数据库还没有这条数据;而改操作建立在数据库已经存在一条即将要被操作的数据条,前端传输的数据中还包括该条数据的id,或者主键,这样以来最大的区别在于是否拥有id,而其他传输数据一致。所以,我的处理方式是加一条判断语句:
...其他数据...
if(paramMap.get("id")!=null){
update(...); //更改数据
}
else{
add(...); //增加数据
}
如果遇到多个相关联的数据表之间的数据增和改操作,比如a表的主键id是b卷的一个字段,如下:
a表:
id|content
-|:-😐:
1|“好”
b表:
id|aId|content
-|:-😐:
1|1|“哈哈哈哈”
2|1|“黑乎乎”
3|1|“嗨嗨嗨”
诸如这样的这张表相互关联,实现增和改操作,我的实现如下(先删后增):
//if语句主要用于修改操作,如果有id则是修改,否则为增加
if(paramMap.get("id")!=null){
a.delete(id); //a表删除数据条
b.delete(id); //b表删除数据条
}
...其他数据...
int id=a.add(数据); //a表增加数据条
b.add(数据,id); //b表增加数据
十六.调试debug快捷键
: Eclipse逐步调试debug快捷键:F6,一步到位:F8
: Ideal逐步调试debug快捷键:F8
: eclipse查看表达式的结果:右击选择watch
十七.@RequestBody
当前端发送数据是一个数组时,如下paramMap,一定记着加上@RequestBody!!!!不然无法接受数据
@RequestMapping("add")
public Result add(@RequestBody Map<String,Object> paramMap){
...code...
}
十八.mapper文件
mapper文件的某些方法比如insert,返回数据类型如果是引用类型,
记着加上resultType或者resultMap
十九.@RestController注解
@RestController注解,相当于@Controller+@ResponseBody两个注解的结合,
返回json数据不需要在方法前面加@ResponseBody注解了,但使用
@RestController这个注解,就不能返回jsp,html页面,视图解析器无
法解析jsp,html页面
二十.数据库的模糊查询
0,-,[]
三个符号的使用,参考博文点击查看
以及下面这种在mapper文件中重要的模糊查询方式!!!
1.字符串模糊查询
SELECT * FROM tableName
<WHERE>
<if test="name !=null">
AND name like CONCAT(CONCAT('%', #{name}), '%')
</if>
</WHERE>
2.时间模糊查询
DATE_FORMAT(Time,’%Y-%m-%d’)的作用在于将时间生成String再做处理
SELECT * FROM tableName
<WHERE>
<if test="time !=null">
AND DATE_FORMAT(Time,'%Y-%m-%d')=#{time} //这里的#{time}是字符串,如果是Date类型,还需要转换
//DATE_FORMAT(#{time},'%Y-%m-%d')
</if>
</WHERE>
二十一.mapper文件@Param的使用
一般在mapper接口的方法中传入参数时,比如int add(User user);
如果提交项目之后出现异常:There is no getter for property user in "xxx.User"
,那么问题原因在于参数的传递需要加上@Param,如:int add(@Param(value="user") User user)
,切记这点
二十二.Jenkins
Jenkins功能包括:
1、持续的软件版本发布/测试项目。
2、监控外部调用执行的工作。