jsp+servlet——给我灵感的一个项目

一、先展示一下我手上的这个项目的结构:

jsp+servlet——给我灵感的一个项目

二、体会项目创建的过程:

1、com文件夹下面的entity(实体层):

jsp+servlet——给我灵感的一个项目

拿user来说,这部分的代码可以分为四部分去理解:

jsp+servlet——给我灵感的一个项目

第一部分:

定义用户属性,注意这里的用户属性和数据库的字段名不一定是一致的,但是一定是一一对应的。

第二部分:

定义构造方法,这里你会发现有两个,一个是有参的构造方法,一个是无参的构造方法。

其实这里我们有讨论到是否需要写无参的构造方法,虽然你在下面没有用到无参的构造方法,而且这里你不写,也不会报错。但是其实在项目中,我们很少用到无参的构造方法。注意是很少,而不是从不会,所以每次写带参数的构造方法时,可以顺带着写一下无参的构造方法,这是一种很好的习惯。

第三部分:

写set和get方法,如果你还在为一行行敲写这些几乎重复的代码而苦恼,那么你有必要了解一些idea中的自动创建set、get方法的快捷键了:

鼠标放在属性名上,右键选择Generate(或者直接按Alt+Insert),选择Getter and Setter

jsp+servlet——给我灵感的一个项目

选择所有属性,一键生成所有的Set和Get方法:

jsp+servlet——给我灵感的一个项目

第四部分:重写toString方法

如果不重写toString方法的话,当你调用它的时候,方法本身返回的就是该对象的实现类的 类名[email protected]+hashcode 的值。所以为了让它能够输出我们想要的信息,就需要对toString方法进行重写。这样一来,就可以输出我们想要的信息了。

2、com文件夹下面的dao:

DAO层,Data Access Object,专门用来封装我们对于实体类的数据库的访问,就是增删改查,不加业务逻辑。
当我们有了DAO层之后,UserManager就不要再去用Hibernate实现或者用XML实现或者用JDBC实现,我们应该调UserDAO。
也就是说在Service层里,我们应该去调用UserDAO。
可以保留一个UserDAO的实例对象,然后调用error()的时候,可以通过UserDAO的方法去查,调用别的什么方法的时候,可以通过UserDAO的方法去查等等。

因为Service层实现连接数据库可以用好几种方法,如Hibernate、XML、JDBC。。。所以我们的UserDAO不能够写死。
如果写死了,就意味着在Service层里调的UserDAO就是死的,UserDAO还是访问数据库的,也就是访问数据库的方式被写死了。
白话讲,就是连接数据库的那部分代码如果想换,就得重写!!!
为了防止麻烦,将UserDAO写成接口。接口可以有多种多样的实现,比如用Hibernate、用XML、用JDBC。。。。
这就是DAO层的作用,将连接数据库的业务逻辑进行封装,如果换了一种连接数据库的方式,可以直接换。
不用再重写代码了。
补充:
由UserDAO负责使用User去和数据库打交道。
对于UserService来说,只需要去访问UserDAO一个就可以了。
由UserDAO负责把User存到数据库里面去!

UserService除了调UserDAO,还可以完成认证等其他功能
也就是说UserService对外公开的只是业务逻辑,UserDAO单纯的只负责跟数据库打交道。

看了上面关于DAO层的一段通俗易懂的解释,你肯定就明白这个DAO里面写的是什么了。没错,就是接口,还有接口的实现类:

jsp+servlet——给我灵感的一个项目

拿UserDao接口来说,这里有4个方法,只有定义,而没有实现,不错,这正是接口的特性...

jsp+servlet——给我灵感的一个项目

然后我们一一去看这些方法的实现:

jsp+servlet——给我灵感的一个项目

这里就只看inserUser的实现方法了,别的实现方法与此大同小异,就不再赘述。

主要注意三个地方:

方框1:通常情况下,我们都会把sql语句直接写到这里:

jsp+servlet——给我灵感的一个项目

像下面那条语句一样,而不是上面那条,也就是我们的项目中的写法。实际上,这里这两种方式的本质是一样的,但是不同的地方在于,前者是将所有的sql语句都封装起来了,就在com目录下的sql文件夹中,代码如下图所示:

jsp+servlet——给我灵感的一个项目

那么我们为什么要这样做?这样做有什么好处呢?

好处就是,这样可以极大地增强代码的可扩展性,而且可以有效的减少你的代码量。具体来讲,就是当你的数据库中的字段改变了,你不需要,去寻找项目中的每一条sql语句,然后一条一条的去改,这样就会很麻烦。当你把sql语句直接封装起来之后,当你的数据库中的字段发生变化的时候,你就只需要更改这里的sql语句就可以,而不需要逐条去查找、更改。

方框2:两个1,2,分别对应sql语句中的两个问号,也就是数据库中的两个字段名。

方框3:涉及数据库信息的更新(增加,修改,删除)时,用executeUpdate();

涉及数据库信息的查找时,用executeQuery()。

3、写完实体类还有DAO层,就差不多可以写测试类了(test文件夹):

jsp+servlet——给我灵感的一个项目

同样,我们这里只看UserTest:

jsp+servlet——给我灵感的一个项目

当然这里关于测试类的创建是直接手动输入的,针对接口实现类中的每一个方法,具体写一个test,而且在每一个test前面一定要手动写 @Test 这个标语,不然的话,无法对每个测试类逐一进行测试。

当然,这里你可能会觉得怎么这么麻烦,有没有什么方法可以直接生成所有接口实现方法的测试类呢?答案是肯定的。


jsp+servlet——给我灵感的一个项目

鼠标放在实现类方法上面,右键,如上图所示操作,或者直接Ctrl+Shift+T,创建测试类:

jsp+servlet——给我灵感的一个项目

确定:

jsp+servlet——给我灵感的一个项目

选中所有的方法,OK:

jsp+servlet——给我灵感的一个项目

你的目录结构下面就会出现这么一个文件夹,文件夹的名称和路径与上面你创建test方法时的Destination package是相对应的。我们再看一下这个UserDaoimplTest中的代码长什么样子:

jsp+servlet——给我灵感的一个项目

可以看到,和上面你手动创建的test文件中代码差不多,基本结构已经都涵盖了,你只需要进行填充就可以了。

4、写完测试类,基本上就已经完成了前期的准备工作。接下来就是真正核心的部分了:jsp+servlet

jsp+servlet——给我灵感的一个项目

正如上图所示,红框部分,就是我们web的核心部分,那么这部分到底是不是你想象中的那么神秘呢?我们一探究竟。

其中方框1所示部分属于前端的代码,这里就不再讲解。我们只看方框2部分的代码,也就是WEB-INF目录下的文件:其中classes文件里面都是前三步准备工作中代码执行之后生成的class文件。lib文件夹需要你手动去创建,主要用来放项目所需要的jar包,记得添加进去以后,右键add library。然后就来到了views文件夹:

jsp+servlet——给我灵感的一个项目

我们在这里主要就是寻找这部分代码和src文件夹下面我们刚刚没有说到的servlet和util文件夹的联系(逻辑关系):

jsp+servlet——给我灵感的一个项目

首先我们先看index.jsp,也就是文件的主页面(注意不是欢迎页,欢迎页我们待会儿会说到在哪里)。代码如下:

jsp+servlet——给我灵感的一个项目

最重要的语句的毫无疑问就是方框中的语句了,那么这条语句表示什么意思呢?

我们先来看一下UserServlet:

jsp+servlet——给我灵感的一个项目

没错,可以发现index.jsp文件中的方框直接就对应上了UserServlet中的两个方框。“/user”是servlet的实际属性名(name不重要,这个才重要)。“state=toLogin”则对应上了UserServlet中的switch语句中的一种case:toLogin。那么我们再看一下toLogin这个case里面又有什么:

jsp+servlet——给我灵感的一个项目

顺着我们之前的思路,我们来到了com文件夹下的util文件夹中的WebContents文件中:

jsp+servlet——给我灵感的一个项目

然后我们发现,和上面说到的sql语句的封装惊人的相似。所以这里就很容易理解了,WebContents.toLogin 实际上就是一个跳转页面的“简称”。那么我们再顺着这个简称去找到真正的jsp页面(也就是真正的欢迎页),所以我们又来到了WEB-INF下views下user文件夹中的login.jsp页面:

jsp+servlet——给我灵感的一个项目

看上面的方框,也就是form表单,有两部分,action和method:action负责跳转到servlet,至于是哪个servlet中的哪个方法,看内容就知道了。我们再去对应的servlet中看一看:

jsp+servlet——给我灵感的一个项目

可以看到,servlet又将功能实现抛给了loginCheck方法:

jsp+servlet——给我灵感的一个项目

在该方法中,就实现了密码的验证。我们可以看到,方框1是用户登录成功时的跳转,会跳转到WebContends.MAIN,通过查看上面的WebContends文件,你会发现,跳转到了main.jsp,也就是主页面了。方框2是用户登录失败时候的跳转,当然还是会跳转到login.jsp,但是此时还会返回一些错误提示,告诉用户你是哪一块的信息填错了。这部分,靠的就是“msg”了,要注意msg一定要在forward前面,因为,一旦forward,就跳转到jsp页面了,所以如果msg在forward后面才出现,那么msg里面的信息是不能够传到jsp页面的。

再就是method了,主要就是post和get的区别:简单来讲就是post更加安全,get相对就没有那么安全。

至此,我们大概已经体会到了servlet+jsp的跳转是怎样一个过程。很简单,index.jsp跳到servlet中,然后跳转到views中的某个jsp页面,然后再返回到servlet中,再跳转到下一个jsp中,这样一个循环往复的过程。

5、数据库列表信息与jsp页面之间的传输:

看feedback.jsp中的一段代码:

jsp+servlet——给我灵感的一个项目

这里就告诉我们列表是怎么传的,就是将反馈放入列表,然后由后台传到前台,前台就通过一个forEach循环去接受,其中的var=“feedBack”就表示当前对象,通过feedBack.correctAnswer可以获取当前对象的任何属性信息。

jsp+servlet——给我灵感的一个项目

至于feedBackList是在哪里定义的,可以去对应的servlet中找,对应的代码在上图中已展示。

当然还有一个问题,就随之出现了。既然前端是通过list获取信息的,但是我们在数据库中存储的信息都是string的形式啊。所以这里就要说到list和string类型之间的一个转换了,也就是数组和字符串之间的一个转换。下面的代码就展示了如何将后台的字符串转换成数组类型,从而使前台便于获取的。

jsp+servlet——给我灵感的一个项目

很容易理解,本质就是没遇到一个逗号,就在字符的左右两边各加一个括号,最后自然就得到一个数组类型。

6、最后再说一下文件的获取和上传吧:

jsp+servlet——给我灵感的一个项目

这里可能会需要修改IntelliJ IDEA中tomcat的输出路径从而避免出现一些不必要的麻烦。

参不多就这么多了吧,从昨天写到现在,我终于写完了。不知道你们看完之后,是否对servlet+jsp有了一些新的理解呢?嘻嘻~