Servlet 3.0 作为 Java EE 6 规范体系中一员,提供了若干新特性用于简化 Web 应用的开发和部署。其中有几项特性的引入让开发者感到非常兴奋,同时也获得了 Java 社区的一片赞誉之声。比如新增了若干注解,用于简化 Servlet、过滤器(Filter)和监听器(Listener)的声明,这使得 web.xml 部署描述文件从该版本开始不再是必选的了。本文就介绍qi中一个很有用的注解: @WebServlet。
搭建一个新的Web项目
打开IDEA,选择创建一个新的Gradle项目,勾选 Java 和 WEB 选项。
点击 NEXT 按钮
输入项目名称 groupid: org.happy ArtifactID: webdemo ,
点击下一步
点击下一步,输入项目名称
点击 Finish 按钮,完成项目创建。
转成 Web 项目
在IDEA中,选中项目,然后点击菜单 File -> Project Structure
在弹出窗口中,左侧选中 Module ,中间点开 项目模块名 webdemo ,右侧 Deployment Descriptors 左下角点击 加号,选择 web.xml
然后可以看见在弹出窗口中已经显示了Web.xml的创建目录。
点击 OK 确认,然后可以修改。
将WEB-INF目录,直接拖入 webapp 目录下。如图
点击OK,确认。
添加Run/Debug config
点击屏幕右上角 三角形 符号附近的下拉菜单,选中 Edit Configurations
点击 加号 -> Jetty Server -> Local
点击 Deployment 页面 ,点击左下角 + 号,选中 Artifact ,在弹出框中选中自己的项目名称,
将 name 改成自己喜欢的名字,如 jetty
点击OK按钮,配置完成。
打开index.jsp文件,随便写点什么,比如 <h1>welcome wedemo!!</h1>
点击 运行按钮,应该可以出现欢迎页面。如下图
编写Model 和 Service
选中 java 文件夹,右键点击 new -> Package ,然后新建 contller model service 三个包
在 model 包中,创建文件 User.java ,我们将创建一个基于用户管理的简单CRUD功能
package org.happy.webdemo.model;
public class User {
private Long id;
private String name;
private String dept;
private String passwd;
}
选中所有字段,然后右键 选择 Generate, 在弹出菜单中选择getter setter,可自动添加 setter getter
生成文件如下:
package org.happy.webdemo.model;
public class User {
private Long id;
private String name;
private String dept;
private String passwd;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
}
在 service 包下添加文件 UserService.java
package org.happy.webdemo.service;
import java.util.ArrayList;
import java.util.List;
import org.happy.webdemo.model.User;
public class UserService {
public List<User> getUserList() {
String sql = "SELECT * FROM user";
List<User> ul = new ArrayList<User>();
User user = new User();
user.setDept("Sales");
user.setName("David");
user.setPasswd("8888");
user.setId((long) 1);
ul.add(user);
User user2 = new User();
user2.setDept("Research");
user2.setName("Tom");
user2.setPasswd("7777");
user2.setId((long) 2);
ul.add(user2);
User user3 = new User();
user3.setDept("Fin");
user3.setName("Kitty");
user3.setPasswd("6666");
user3.setId((long) 3);
ul.add(user3);
return ul;
}
}
这里仅仅简单模拟取出所有用户信息。实际操作中可连接数据操作。
5. 使用 @WebServlet 编写 Controller
在controller包中添加文件 UserListServlet, 添加代码如下
package org.happy.webdemo.controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.happy.webdemo.model.User;
import org.happy.webdemo.service.UserService;
@WebServlet("/users")
public class UserListServlet extends HttpServlet {
private UserService userService;
@Override
public void init() throws ServletException {
userService = new UserService();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<User> userList = userService.getUserList();
req.setAttribute("userList", userList);
req.getRequestDispatcher("/WEB-INF/view/users.jsp").forward(req, resp);
}
}
6. 在构建文件 build.gradle 中添加相关依赖
修改后文件如下
group 'org.happy'
version '1.0'
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'jetty'
sourceCompatibility = 1.5
repositories {
//mavenCentral()
maven { url 'http://maven.oschina.net/content/groups/public/' }
}
dependencies {
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
providedCompile 'javax.servlet.jsp:jsp-api:2.2'
runtime 'javax.servlet:jstl:1.2'
compile 'org.slf4j:slf4j-log4j12:1.7.7'
testCompile group: 'junit', name: 'junit', version: '4.11'
}
7. 添加 users.jsp 文件,用户用户信息显示
在WEB-INF目录下添加 view 目录,然后添加 users.jsp 文件如下
<%@ page pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>用户管理</title>
</head>
<body>
<h1>用户列表</h1>
<table>
<tr>
<th>用户名</th>
<th>部门</th>
<th>密码</th>
</tr>
<c:forEach var="user" items="${userList}">
<tr>
<td>${user.name}</td>
<td>${user.dept}</td>
<td>${user.passwd}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
8. 点击运行按钮,在浏览器中输入 http://localhost:8080/webdemo-1.0/users ,可以看到显示出的用户信息列表。
9. 小结
1) 使用 @WebServlet 不再需要配置 web.xml 就可以根据路径设置直接定位到 对应的Controller 中
2) 注意在 doGet中,我们使用的 req.getRequestDispatcher().forward 来进行页面结果显示。这其中牵涉到 forward 和 redirect的区别。这是一种通用做法,因为forward可以传递 Request级别的数据。
3) 构建工具Gradle的配置文件 build.gradle 中,我们用到了 providedCompile runtime compile 等几个选项,他们是有区别的。
10. 附录
1). forward VS redirect
A. 从地址栏显示来说
forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.
B. 从数据共享来说
forward:转发页面和转发到的页面可以共享request里面的数据.
redirect:不能共享数据.
C. 从运用地方来说
forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等.
2) provided compile runtime 等含义
provided 只参与编译,而无需参与打包,比如 tomcat自带了 JSP 和 SERVLET 的JAR包
runtime 不参与编译,只是运行时需要,如JSTL
在Maven中,这样来限制Scope
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency>
在Gradle中,这样来定义
dependencies {
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
providedCompile 'javax.servlet.jsp:jsp-api:2.2'
runtime 'javax.servlet:jstl:1.2'
compile 'org.slf4j:slf4j-log4j12:1.7.7'
testCompile group: 'junit', name: 'junit', version: '4.11'
}