如果你想开发一个应用(1-4)

样式与布局

前一章中,我们已经完成了一个todos应用的最基础的功能,但不可否认的是,这个应用看起来太简陋了,几乎没有任何吸引力,而很明显,我们想要开发一个应用的目的就是让人来使用它,哪怕仅仅是自己使用(好惨),也喜欢有一个赏心悦目的ui吧

下面我们想要实现的效果如下:

  • 一个精美,显眼的输入框,用于新建清单或者为已有清单增加待办事项
  • 输入框居中,并且使用框体增加用户注意力

实现这个目标,并不是很简单的事,尤其是假定还要使用手机,平板电脑等设备来访问,所以,对于我这种懒人来说,最好的方法是使用css框架,目前css框架有很多,比如赫赫有名的Bootstrap,但毕竟Bootstrap使用的太广泛了,难免有千篇一律之嫌,所以就此考虑,使用了一个占有率稍小的前端框架:Semantic UI

Semantic UI也可以使用Bootstrap提供的cdn来获取,在页面头部增加cdn的引用:

<link href="https://cdn.bootcss.com/semantic-ui/2.2.13/semantic.min.css" rel="stylesheet">

当然,实际项目中可不能这么干,有个好的UI设计和前段开发还是很必要的,因为即使占有率不让Bootstrap那么高,用户也立刻就能看出你使用的默认的样式,给人一种你甚至连自己定制都懒得动的感觉:(

下面使用Semantic UI的强大功能对页面进行一下修改(这里强烈建议看一下Semantic UI文档):

<div class="ui two column centered relaxed  grid">
    <div class="column row"></div>
    <div class="column ">
        <h2 class="ui huge header center violet aligned">jTodos!</h2>
        <div class="ui raised segment">
            <form action="index.jsp" method="post"  class="ui fluid action input">
                <input type="text" name="todo" placeholder="请输入一个备忘录项目">
                <button type="submit" class="ui button">OK</button>
            </form>
            <div class="ui aligned huge selection divided list">
                <c:forEach var="item" items="${todos}">
                    <div class="item">
                            <span class="header">${status.index+1}.${item}</span>
                    </div>
                </c:forEach>
            </div>
        </div>
    </div>
</div>

这段html中可以看出SemanticUI的特点,就是采用多种css类组合的方式,强调不同的css类的服用,这段代码最后执行的页面效果如下:

image

注意:此处严禁吐槽配色!!!

数据模型

对于一个todos来说,现在我假设你希望知道你这个idea的迸发时间,也就是item项发出创建的时间,这时候,就会发现单纯的使用字符串已经满足不了需求了,这时候,就轮到数据模型出场了。
一般来说,项目中会把数据模型统一管理,这里我们也来创建一个单独用于数据模型管理的包

此处不同版本的IntelliJ Idea的显示会不同

首先找到项目的main文件夹,在文件夹下创建java文件夹用来放置代码文件,但此时java文件夹为普通文件夹,需要把他修改为idea可识别的代码文件夹,修改方式如下:
修改前:

image

然后依次选择 file->Project Structure,
在弹出的窗体中选择java文件夹:

image

选择java文件夹,然后设置为Sources模式:

image

然后点击apply,最后点击ok,即可设置完成。

再次强调,此操作与Intellij Idea的版本有关,如果你的版本默认自带代码文件夹,则不需要此步骤。

完成准备工作,我们开始创建模型所在的包,以方便对数据模型的管理,包名一般都为域名的逆序,以保证唯一性,这里包名为:

com.niufennan.jtodos.models

然后创建一个数据类,暂时命名Todo,只做简单的演示,这里类中只有三个字段以及相应的封装,这个类的源代码如下:

package com.niufennan.jtodos.models;
import java.util.Date;
public class Todo {
    private int id;
    private String item;
    private Date createTime;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getItem() {
        return item;
    }
    public void setItem(String item) {
        this.item = item;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}

这样,每次新增的就不再是一个字符串项,而是一个Todo的数据模型,也就是所谓的一个javabean了。

修改代码如下:

<%
    request.setCharacterEncoding("utf-8");
    List<Todo> todos=(List<Todo>) application.getAttribute("todos");
    if(todos==null){
        todos=new ArrayList<>();
        application.setAttribute("todos",todos);
    }
    if(request.getParameter("todo")!=null){
        Todo todo=new Todo();
        todo.setCreateTime(new Date());
        todo.setItem(request.getParameter("todo"));
        todos.add(todo);
    }
%>

html模板部分修改为:

<c:forEach var="todo" varStatus="status" items="${todos}">
    <div class="item">
        <span class="header">${status.index+1}.${todo.item}</span>
    </div>
</c:forEach>

运行,效果入下:

image

与之前一模一样。

注意,这种随便改变数据类型的方法,为开发中大大忌,在实际开发中是严禁禁止的行为,但这篇blog为了照顾各个知识点,所以并未从开始进行整体架构设计,以后这种修改数据类型的行为会经常发生。
在此强调一遍,此为开发中的大忌,要严格禁止。

但是,你可能发现了,并没有出现这个todo项创建的时间呀,下面我们把创建时间写入数据模板,修改的代码如下:

 <c:forEach var="todo" varStatus="status" items="${todos}">
    <div class="item">
        <span class="right floated content">${todo.createTime}</span>
        <span class="left floated header">${status.index+1}.${todo.item}</span>
    </div>
</c:forEach>

显示效果为:

image

效果很明显,显示上符合了要求,但是,日期的格式很明显是错误的呀,这时候要对日期格式进行修改,就牵扯到在jsp中书写java方法,jsp中写java方法也很简单,写在代码框<%! code %>中即可,注意前边的!,实际代码如下:

<%!
    private String formatDate(Date date){
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = formatter.format(date);
        return dateString;
    }
%>

页面调用的方式如下:

<%
      for (int i=0;i<todos.size();i++) {
  %>
  <div class="item">
      <span class="right floated content"><%= formatDate(todos.get(i).getCreateTime())%></span>
      <span class="left floated header"><%=i+1%>.<%=todos.get(i).getItem()  %></span>
  </div>
  <%
      }
  %>

执行结果如下:

image

但是,你可能注意到了,我们又回到了html中嵌入代码的老路,这是因为jstl和java代码的调用问题,难道就不能不适用这种嵌入的方法么,答案是当然可以,jstl也提供了日期格式化的方式,首先在页面顶部引入前缀:

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

然后jstl下模板的写法:

<c:forEach var="todo" varStatus="status" items="${todos}">
  <div class="item">
      <span class="right floated content"><fmt:formatDate value="${todo.createTime}" type="date" pattern="yyyy-MM-dd HH:mm:ss"/></span>
      <span class="left floated header">${status.index+1}.${todo.item}</span>
  </div>
 </c:forEach>

注意pattern参数.

运行一下,显示的结果应该是与之前没有任何差别.

然后,就可以开开心心的把原来的格式化方法删除了.

本章的也将告于段落,从下一章开始,就会进入servlet和模块化的javabean的世界,难度应该会增加不少,不管怎么说,感谢您的阅读.

注意:本章第三次提醒!!!
Blog仅仅是为了介绍知识点,在实际项目中严禁使用这里使用的一些编码方式,对于由此产生的任何后果,本blog概不负责!!!

感谢您的阅读