Fork me on GitHub

项目开发过程

注意:所有文章除特别说明外,转载请注明出处.

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 文件流

我们衡量输入、输出时总是站在运行本程序所在内存的角度。


javascript –> replace(/-/g, “/“) /-/g 是正则表达式,表示素有短横线替换为斜杠,其中g表示全局替换。


本文标题:项目开发过程

文章作者:Bangjin-Hu

发布时间:2019年10月15日 - 09:22:26

最后更新:2020年03月30日 - 08:13:23

原始链接:http://bangjinhu.github.io/undefined/项目开发过程记录/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Bangjin-Hu wechat
欢迎扫码关注微信公众号,订阅我的微信公众号.
坚持原创技术分享,您的支持是我创作的动力.