注意:所有文章除特别说明外,转载请注明出处.
1.Tomcat与jetty
jetty和Tomcat是两款著名的开源webserver/servlet容器。
两者之间的比较:
1.jetty更加的轻量级
2.jetty更加灵活,表现在可扩展性
2.web.xml文件配置
修改在webapp
路径下的web.xml
文件需要根据规定的顺序添加操作权限,否则会报错。或者将<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
这一段校验代码删掉,问题就解决了。这时因为我们添加的部分的代码符合xml
文档规范,但是不符合web-app_2_3.dtd
所定义的规范。
3.测试
注意:在使用IDEA开发的时候,mapper类只能建立在resource目录下,不能建立在Java的包下面,不然会映射不了。
1.首先编写entity
2.然后编写接口
3.接下来使用mapper
4.最后编写测试用例,直接使用junit测试
//测试dao层
// 使用Springtest测试框架
@RunWith(SpringJUnit4ClassRunner.class)
// 加载配置
@ContextConfiguration("/spring/spring-*.xml")
public class MyBatisTest {
@Autowired
private ScoreDao scoreDao;
@Test
public void testAddScore() {
Score score = new Score();
score.setChangeType("充钱钱");
score.setScore(10);
int insert = scoreDao.insertScore(score);
System.out.print("insert :"+insert);
}
}
5.测试整个框架(使用SpringMVC)
1.编写业务逻辑接口
2.然后编写业务逻辑接口的实现类
3.然后编写controller将springmvc的解析视图解析出来
4.Redis 单机版以及测试版
5.SSM 项目开发
1.配置文件
Service接口文件与ServiceImpl实现类文件
1.ServiceImpl文件
对于ServiceImpl中的文件只是实现Service接口中的方法函数,在Service接口的返回类型:
1.一般表示操作(删除/更新/添加)的方法函数返回Boolean类型。
2.表示查找返回其需要的类型(实体类型/实体类型的List)。
实现步骤:
1.在接口类实现之前添加@Service注解
2.然后在class中注入相关的mapper接口
3.最后实现相关的方法函数
2.Service文件
对于Service文件只是声明此文件中将要实现的方法函数。
1.http 400 error
http 400 错误表示请求无效(bad request) 在ajax请求后台数据时会报http 400 错误,表示这个请求没有进入后台服务里。
原因:
1.前端提交数据的字段名称或者或者字段类型和后台的实体类不一致,或者前端提交的参数跟后台需要的参数不一致,导致参数无法封装。
2.前端提交到后台的数据应该是JSON字符串类型,而前端没有将此对象转化为字符串类型。解决方案:
1.对照字段名称、类型保证一致性。
2.使用stringify将前端传递的对象转化为字符串 如:data:JSON.stringify(param);
1.JSON.toJSON()
方法可以将Date对象转换为字符串,并格式化为JSON数据格式。
var Date = new Date();
var Date_New = Date.toJSON();
2.JSON.toJSONString()
方法将对象转换为JSON格式数据。
Spring 开发注解
1.@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT) 表示该类需要Spring加入事务,propagation=Propagation.REQUIRED 属性指有事务就处于当前事务中,没有事务就创建一个事务。isolation=Isolation.DEFAULT 表示使用事务的默认隔离级别。
.tld文件
调试错误 状态码(400 404等)
1. http 400(Bad request)
在ajax请求后台数据时有时会报 HTTP 400 错误 - 请求无效 (Badrequest),出现这个请求无效报错说明请求没有进入到后台服务
里。
原因:
1)前端提交数据的字段名称或者是字段类型和后台的实体类不一致,导致无法封装。
2)前端提交的到后台的数据应该是json字符串类型,而前端没有将对象转化为字符串类型。
解决方案:
1)对照字段名称,类型保证一致性
2)使用stringify将前端传递的对象转化为字符串
data: JSON.stringify(param)。
2. 空指针异常
1.空指针异常发生情况
1.字符串变量没有初始化
2.接口类型的对象没有用具体的类初始化
如:
List list;//这个就会报错
List list = new ArrayList();//这就不会报错
3.在一个对象的值为空,而我们没有判断为空的情况时会报错
2.空指针异常解决方案
重点关注报错发生在的行,通过空指针异常产生的两条主要原因诊断具体的错误。同时为了避免空指针的发生,最好在做判断处理时将“null”或者空值放于设定的值之前。
注意:大多数的空指针异常都是与对象的操作相关
3. springmvc
//判断obj是否空指针,如果是则抛出空指针异常
Objects.requireNonNull(obj);
1.修
//这表示修改之前首先获取到需要修改的信息,返回给前台
@RequestMapping("/student/mod/{sid}")
public String student_modify(@PathVariable("sid") Integer sid, Model model, HttpSession session) {
Objects.requireNonNull(sid);
Student student = studentService.findById(sid);
Integer tid = (Integer) session.getAttribute(Constant.SESSION_KEY_FOR_TEACHER_ID);
Teacher admin = teacherService.findById(tid);
model.addAttribute("student", student);
model.addAttribute("admin", admin);
return "admin/student_mod";
}
//表示在上面的获取修改的值之后,在这里执行修改操作
@RequestMapping("/student/mod/do")
public String student_modify_do(Student student) {
LOG.info("modify: " + student);
student.setYear(Integer.valueOf(student.getGrade()) + 4 + "");
studentService.saveOrUpdate(student);
return "redirect:/admin/student";
}
2.删
//这里表示根据所在项的id值删除该项
@RequestMapping("/student/dlt/{sid}")
@ResponseBody
public Object student_delete(@PathVariable("sid") Integer sid, Model model) {
Map<String, Object> result = new HashMap<>();
LOG.info("delete student: sid = " + sid);
Student student = studentService.findById(sid);
try {
studentService.delete(sid);
LOG.info("delete student = " + student);
result.put("code", ResultCodeEnum.SUCCESS.getVal());
} catch (Exception e) {
result.put("code", ResultCodeEnum.FAILED.getVal());
}
return result;
}
3.增
//首先给出添加页面
@RequestMapping("/student/add")
public String student_add(Model model, HttpSession session) {
Integer tid = (Integer) session.getAttribute(Constant.SESSION_KEY_FOR_TEACHER_ID);
Teacher admin = teacherService.findById(tid);
model.addAttribute("admin", admin);
return "admin/student_add";
}
//增加操作
@RequestMapping("/student/add/do")
public String student_add_do(Student student) {
LOG.info("add student = " + student);
studentService.saveOrUpdate(student);
return "redirect:/admin/student";
}
4.DataTables分页插件
@RequestMapping(value = "/thesis-varify/process/{year}/{modify}", produces = {"application/json;charset=UTF-8"})
@ResponseBody
public Object thesisVarifyProcess(@PathVariable("year") String year,
@PathVariable("modify") Integer modify,
//这标签的作用是将其绑定在request上面
@DataTableArgument DataTableRequest dtRequest,
@RequestParam(value = "showColumns[]", required = false) String[] showColumns) {
//新建的接收前台的数据容器
DataTableResponse<ThesisVarifyVo> dtResponse = new DataTableResponse<>();
if (modify == -1) modify = null;
List<ThesisVarifyVo> thesisVarifyVos = adminService
.queryThesisVarifyVoForDataTable(dtRequest, showColumns, year, modify);
//然后将从数据库中查询到的数据封装到返回前台的容器中
dtResponse.setData(thesisVarifyVos);
//表示查询的数据
dtResponse.setRecordsFiltered(adminService
.countFilteredThesisVarifyVoForDataTable(dtRequest, showColumns, year, modify));
//表示总的记录
dtResponse.setRecordsTotal(adminService.countTotalThesisVarifyVoForDataTable());
dtResponse.setDraw(dtRequest.getDraw());
return JSON.toJSONString(dtResponse);
}
5.DataTables服务端参数
1.发送到服务器端的参数
draw 计数器,返回数据用这个记录
start 开始记录
length 每页条数
search[value] 检索文字
order[i][column] int 排列列的序号,i表示有几个排序 order[0][column]表示有一个服务器端
order[i][dir] 排序方式“desc” “asc”
注:下面comuns中的i取值从0~columns.length,所有的columns信息都发送到了服务器
columns[i][data]:columns上定义的data属性值
columns[i][name]:columns上定义的name属性值
columns[i][searchable]:列能不能检索
columns[i][orderable]:列能不能排序
columns[i][search][value]:列的检索值 string
2.服务器返回的数据
draw:和Request的draw设定成一样的值
recordsTotal:所有的总件数
recordsFiltered:筛选后的总件数
data:返回的数据
每一行数据上面,可以包含这几个可选项
DT_RowId:加在行上的ID值
DT_RowClass:加在行上的Class
DT_RowData:加在行上的额外数据(object)
DT_RowAttr:加在行上的属性(object)
error:如果有错误,就设定这个值,没有错误,不要包含这个值
前台向后端传参数
1.get方式
<a href="/teacher/coursework/export?courseName=${tWorks.courseName}" class="btn btn-success"><i class="fa fa-download"></i> 下载《${tWorks.courseName}》作业表</a>
2.post方式
mysql联合查询(3表联合查询)
//最开始的mysql 3表联合查询语句
SELECT
student_course_work.sclass,
student.sname,
student.sno,
student_course_work.submit_time,
teacher_course_work.course_name
FROM
student_course_work
INNER JOIN student ON student.id = student_course_work.sid
INNER JOIN teacher_course_work ON teacher_course_work.tid = student_course_work.tid
WHERE
course_id = #{courseId}
注意:这里需要说明一点的就是,这里的联合查询会出现重复的结果,所以在这种情况下的查询是不能使用的。
//修改后的mysql联合查询语句
SELECT
student_course_work.sclass,
student.sname,
student.sno,
student_course_work.submit_time,
teacher_course_work.course_name
FROM
student_course_work
INNER JOIN student ON student.id = student_course_work.sid
INNER JOIN teacher_course_work ON teacher_course_work.id = student_course_work.course_id
WHERE
course_id = #{courseId}
FreeMarker - contains & seq_contains
1.contains
该字段是String上的方法,作用与字符串上,主要用来查找字符串或者字符是否存在在指定的字符串中,返回true or false。
2.seq_contains
如果要判断序列中是否包含某个指定的元素,可以使用序列的内建函数seq_contains。
注1:seq_contains这个内建函数从FreeMarker 2.3.1 版本开始可用。而在2.3版本中不存在。
注2:在开发过程中,该查找的参数大多数情况下都是返回数据,需要注意数据类型一致,如果数据类型不一致会报错。
权限 Permissions
权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。
1.在执行视图的dispatch()方法前,会先进行视图访问权限的判断
2.在通过get_object()获取具体对象时,会进行对象访问权限的判断
Map
在向map中插入值的时候,注意前后类型的区别。
Map<String, String> map = new HashMap<>();
//key和value值的类型都是String
map.put("name",name);
Map<String, Integer> map = new HashMap<>();
//key和value的值分别是String和Integer
map.put("sno",sno);
Map<String, Object> map = new HashMap<>();
//key的类型必须是String,而sno的类型可以是任意的,Integer,String等。
map.put("sno",sno);
List
获取List集合中的一行,使用list.get(i)
,然后再获取该行中的某一列list.get(i).getName();
Ajax提交表单 SpringMVC接收
1.serialize()方法
1.1 前台JavaScript的编写
function insert(){
$.ajax({
type:"POST",
url:"${pageContext.request.contextPath}/order/insert",
data : $("#fom").serialize(),
success :function (res) {
console.log(res);
error:function () {
}
});
}
1.2 后台SpringMVC的数据接收
@RequestMapping(value = "/insert",method = RequestMethod.POST)
public String insert( Order order){
int result=this.orderSerivce.insert(order);
if(result==1){
System.out.println("添加失败");
return "101";
}
return "100";
}
注意:后台SpringMVC用对象参数接收,可以自动转换为对象,需要注意name要和对象中的参数名相同。
2.JSON.stringify()
2.1 前台程序的编写
function insert(){
$.ajax({
type:"POST",
url:"${pageContext.request.contextPath}/user/insert",
async:false,
data :JSON.stringify({
username : $("input[name='username']").val(),
password: $("input[name='password']").val(),
role : {
id : "",
name: $("select[name='name']").val()
}
}),
contentType: "application/json;charset=UTF-8",
/*如果不写这个,仔细看后台会出现Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported */
dataType:"json",
success :function (res) {
console.log(res);
if(res==100){
$("#msg").html("<font size='60px'> success </font>").show(700).delay(3000).hide(500);
}else {
$("#msg").html("<font size='60px'> fail </font>").show(700).delay(3000).hide(500);
}
window.location.href="http://localhost:8080/user/findall?page=1"
},
error:function () {
$("#msg").html("<font size='60px'> fail </font>").show(700).delay(3000).hide(500);
window.location.href="http://localhost:8080/user/findall?page=1"
}
});
}
2.2 后台程序的编写
@ResponseBody
@RequestMapping(value = "/insert",method = RequestMethod.POST)
public String insert(@RequestBody User user){
int result=this.userSerivce.insert(user);
if(result==0){
return "101";
}
return "100";
}
注意:后台用@RequestBody接收, @RequestBody只接收JSON对象的字符串,所以在前台开始的时候需要将json格式对象转换成json格式对象的字符串格式。
2.3 JSON.parseObject() | JSON.toJSONString() 区别
JSON.parseObject,是将Json字符串转化为相应的对象;JSON.toJSONString则是将对象转化为Json字符串。
SpringMVC 项目开发经验
Java 文件流
我们衡量输入、输出时总是站在运行本程序所在内存的角度。