Servlet JSP
Java Web应用的目录结构
Java Servlet 规范规定了严谨的目录结构必须
webapp
|--WEB-INF 用户不能直接访问的文件夹
| |-- web.xml 部署描述文件
| |-- classes 编译以后的Java 类文件, 包括Servlet等
| |-- lib 第三方的库, 比如jdbc驱动等
|--post.html 直接发布的文件: html, js, css 等
Eclipse会自动将项目发布到 Tomcat 中:
Servlet JDBC 编程
导入JDBC驱动
Maven项目中导入的Jar会自动发布到 WEB-INF/lib 文件夹中.
步骤:
-
导入 mysql 驱动
mysql-connector-java mysql-connector-java 5.1.37 部署
检查 Tomcat 里面的Web应用中WEB-INF/lib里面是否有mysql connector jdbc jar.
导入测试框架 JUnit
JUnit是企业中必备的Java测试工具, 其使用步骤为:
-
导入JUnit组件
junit junit 4.12 test 这里
表示JUnit组件不发布到Web 应用的WEB-INF/lib文件夹下,只是在Eclipse项目中有效
scope 范围 -
创建测试案例:
public class TestCase { @Test public void testHello() { System.out.println("Hello World!"); } @Test public void testKitty() { System.out.println("Hello Kitty!"); } }
测试: 在Eclipse中可以对每个测试方法单独执行, 测试结果显示在JUnit视图标签中.
编写DBUtils封装数据库连接
-
编写DBUtil
public class DBUtil { private static String driver; private static String url; private static String username; private static String password; //读取配置文件,获取4个连接参数 conf.properties static{ try { //读取resource中的配置文件 String file="conf.properties"; InputStream in = DBUtil.class .getClassLoader() .getResourceAsStream(file); Properties config=new Properties(); config.load(in); driver=config.getProperty("driver"); url=config.getProperty("url"); username=config.getProperty("username"); password=config.getProperty("password"); //打桩!!! } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } public static Connection getConnection() throws SQLException { try { Class.forName(driver); Connection conn = DriverManager.getConnection( url, username, password); return conn; } catch (ClassNotFoundException e) { e.printStackTrace(); throw new SQLException(e); } } public static void commit(Connection conn){ if(conn!=null){ try { conn.commit(); } catch (SQLException e) { e.printStackTrace(); } } } public static void rollback(Connection conn){ if(conn!=null){ try { conn.rollback(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(Connection conn){ if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
-
利用JUnit测试:
@Test public void testCConnection() throws SQLException { //测试数据库的连接 Connection conn = DBUtil.getConnection(); System.out.println(conn); DBUtil.close(conn); }
Servlet直接调用JDBC可以直接编写程序,程序会复杂繁琐:
步骤为:
-
编写Servlet
/** * 实现显示用户列表的功能 */ public class ListUserServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //连接到数据库 //查询结果 //将查询结果拼接为HTML //返回HTML内容 //状态默认值是200 response.setContentType("text/html;charset=utf-8"); //设置Body中的文本编码为 utf-8 response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); //输出头部 out.println(""); out.println(""); out.println(" "); out.println(" "); out.println(" "); out.println("
用户列表
"); Connection conn = null; try { conn = DBUtil.getConnection(); //执行SQL String sql = "select * from user"; Statement st = conn.createStatement(); ResultSet rs = st.executeQuery(sql); //输出头部... out.println(""); out.println("
"); } catch (SQLException e) { e.printStackTrace(); //抛出异常返回 500 错误页面 throw new ServletException(e); } finally { DBUtil.close(conn); } out.println(" "); out.println(""); } }"); out.println(" 编号 "); out.println("用户名 "); out.println(""); while(rs.next()) { //读取查询结果 //输出 每一行数据 out.println(" "); out.print(" "); } //输出尾部 out.println(""); out.print(rs.getInt("id")); out.println(" "); out.print(""); out.print(rs.getString("username")); out.println(" "); out.println("拼接table的思路如下:
-
配置web.xml
ListUserServlet ListUserServlet day03.ListUserServlet ListUserServlet /user/list -
测试:
http://localhost:8080/servlet1/user/list
利用MVC模式实现用户列表功能
上述案例可以看到, 数据访问代码和HTML代码混合在一起, 混乱不堪, 并且当HTML页面内容复杂时候, 就更加难于驾驭代码.
在WEB编程中采用MVC模式, 将数据访问\显示视图和控制流程加以分离, 这样可以应付复杂HTML页面处理.
实现步骤
- 编写实体类User:
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private String email;
private String mobile;
private Date createTime;
public User() {
}
public User(Integer id, String username, String password, String email, String mobile, Date createTime) {
super();
this.id = id;
this.username = username;
this.password = password;
this.email = email;
this.mobile = mobile;
this.createTime = createTime;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", email=" + email + ", mobile="
+ mobile + ", createTime=" + createTime + "]";
}
}
-
编写Dao封装数据访问逻辑
Dao 接口:
public interface UserDao { /** * 查询全部用户信息 * @return 包含全部用户信息的集合 */ List
findAllUser(); } Dao实现类:
public class UserDaoImpl implements UserDao{ public List
findAllUser() { Connection conn = null; try { conn = DBUtil.getConnection(); String sql = "select * from user"; Statement st = conn.createStatement(); ResultSet rs = st.executeQuery(sql); List list = new ArrayList (); while(rs.next()) { User user = new User(); user.setId(rs.getInt("id")); user.setUsername(rs.getString("username")); user.setPassword(rs.getString("password")); user.setEmali(rs.getString("email")); user.setMobile(rs.getString("mobile")); user.setCreateTime(rs.getTimestamp("create_time")); list.add(user); } return list; } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } finally { DBUtil.close(conn); } } } -
测试Dao
@Test public void testFindAllUser(){ //测试 查询全部用户信息的方法 UserDao dao = new UserDaoImpl(); List
list=dao.findAllUser(); for (User user : list) { System.out.println(user); } } -
编写 ListAllServlet 作为控制器
public class ListAllServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //利用Dao查询数据 //将请求转发到 另外一个 Servlet显示数据 UserDao dao = new UserDaoImpl(); List
list = dao.findAllUser(); //将需要传递的数据 放置到request对象中 req.setAttribute("users", list); //list = req.getAttribute("user"); String path = "user/view"; //String path="/WEB-INF/view/users.jsp"; //request API 提供了 Servlet之间协作处理 //的功能, forward: 协作(请求)转发 RequestDispatcher rd = req.getRequestDispatcher(path); } } 注意这个 控制器 必须依赖 显示组件 才能工作
-
配置 web.xml
ListAllServlet ListAllServlet controller.ListAllServlet ListAllServlet /user/listall -
编写视图 ViewServlet
public class ViewServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //显示组件,只负责显示用户信息 //获得用户信息 List
users = (List ) req.getAttribute("users"); System.out.println("users"+users); resp.setContentType("text/html;charset=utf-8"); resp.setCharacterEncoding("utf-8"); PrintWriter out = resp.getWriter(); out.println(""); out.println(""); out.println(""); out.println(""); out.println(""); out.println(""); out.println(" 全部用户
"); out.println(""); out.println("
"); out.println(""); out.println(""); } }"); out.println(" "); for (User u : users) { out.println("编号 "); out.println("用户名 "); out.println(""); out.print(" "); } out.println(""); out.print(u.getId()); out.println(" "); out.print(""); out.print(u.getUsername()); out.println(" "); out.println(" -
配置 web.xml
ViewServlet ViewServlet view.ViewServlet ViewServlet /user/view 测试
http://8080/servlet1/user/listall
JSP
JSP Java 推荐的视图组件,用于解决Servlet作为视图使用非常繁琐的问题,JSP按照HTML语法编写,在运行期间解释为Servlet工作:
编写JSP实现视图组件功能:
-
编写JSP实现视图组件功能:
<%@ page import="java.util.List,entity.User" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
用户列表 用户JSP
编号 用户名 users = (List )request.getAttribute("users"); for(User u: users){ %> <%=u.getId() %> <%=u.getUsername() %> 这里将JSP保存在 WEB-INF文件夹的目的是为了避免视图组件被用户之间访问出现异常信息。
-
重构控制器 LustServlet,更新视图组件:
... //转发到视图显示users数据 String path="/WEB-INF/view/users.jsp"; //request API 提供了 Servlet之间协作处理 //的功能,forward: 协作(请求)转发 RequestDispatcher rd = req.getRequestDispatcher(path); rd.forward(req,resp); ...
-
测试:
http://localhost:8080/servlet/user/listall
后续课程讲解详细的 JSP语法
- JSP 指令 <%@ %>
- JSP 脚本 <% ... %>
- JSP 表达式 <%=表达式%>
作业
- 实现课堂案例
- 利用 Servlet/JSP 配合实现 商品列表