我的Java Web之路 – 租房网应用完整代码

  • Post author:
  • Post category:java


本系列文章旨在记录和总结自己在Java Web开发之路上的知识点、经验、问题和思考,希望能帮助更多码农和想成为码农的人。

本文转发自头条号【普通的码农】的文章,大家可以关注一下,直接在今日头条的移动端APP中阅读。因为平台不同,会出现有些格式、图片、链接无效方面的问题,我尽量保持一致。

原文链接:

https://www.toutiao.com/i6764266772968243715/



介绍

本篇文章给出截止到

上篇文章

之时,租房网应用的完整代码。



工程结构

在这里插入图片描述



POM文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>house-renter</groupId>
 <artifactId>house-renter</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>war</packaging>
 <dependencies>
 <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>5.2.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-webmvc</artifactId>
 <version>5.2.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.taglibs/taglibs-standard-impl -->
<dependency>
 <groupId>org.apache.taglibs</groupId>
 <artifactId>taglibs-standard-impl</artifactId>
 <version>1.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.taglibs/taglibs-standard-spec -->
<dependency>
 <groupId>org.apache.taglibs</groupId>
 <artifactId>taglibs-standard-spec</artifactId>
 <version>1.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
<dependency>
 <groupId>com.h2database</groupId>
 <artifactId>h2</artifactId>
 <version>1.4.200</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-jdbc</artifactId>
 <version>5.2.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>druid</artifactId>
 <version>1.1.21</version>
</dependency>
 </dependencies>
 <build>
 <plugins>
 <plugin>
 <artifactId>maven-compiler-plugin</artifactId>
 <version>3.8.0</version>
 <configuration>
 <source>1.8</source>
 <target>1.8</target>
 </configuration>
 </plugin>
 <plugin>
 <artifactId>maven-war-plugin</artifactId>
 <version>3.2.1</version>
 <configuration>
 <warSourceDirectory>WebContent</warSourceDirectory>
 </configuration>
 </plugin>
 </plugins>
 </build>
</project>



Web部署描述符 – web.xml

主要是用来配置 Spring MVC 的 DispatcherServlet 。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	id="WebApp_ID" version="3.0">
	<display-name>house-renter</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	<filter>
		<filter-name>characterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>characterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/dispatcher.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>*.action</url-pattern>
	</servlet-mapping>
</web-app>



Spring IoC配置元数据 – dispatcher.xml

主要用来开启组件扫描、配置DataSource和JdbcTemplate这两个Bean。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		https://www.springframework.org/schema/beans/spring-beans.xsd 
		http://www.springframework.org/schema/context
		https://www.springframework.org/schema/context/spring-context.xsd">
	
	<context:component-scan base-package="houserenter"/>

	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<property name="url" value="jdbc:h2:~/h2db/houserenter" />
		<property name="username" value="sa" />
		<property name="password" value="" />

		<property name="maxActive" value="20" />
		<property name="initialSize" value="1" />
		<property name="maxWait" value="60000" />
		<property name="minIdle" value="1" />
	</bean>
	
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<constructor-arg ref="dataSource" />
	</bean>
</beans>



Java代码 – 控制器层

package houserenter.controller;
import java.io.UnsupportedEncodingException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import houserenter.entity.House;
import houserenter.service.HouseService;
@Controller
public class HouseRenterController {
	
	@Autowired
	private HouseService houseService;
	@GetMapping("/test.action")
	@ResponseBody
	public String test() {
		return "hello";
	}
	@PostMapping("/login.action")
	public ModelAndView postLogin(String userName, String password) {
		//这里需要验证用户是否已经注册,省略
		System.out.println("userName: " + userName + ", password: " + password);
		ModelAndView mv = new ModelAndView();
		//重定向到查找感兴趣房源列表的动作
		mv.setViewName("redirect:houses.action?userName=" + userName);
		return mv;
	}
	@GetMapping("/houses.action")
	public ModelAndView getHouses(String userName) {
		//这里需要验证用户是否登录,省略
		
		ModelAndView mv = new ModelAndView();
		//查找感兴趣房源并绑定到相应JSP页面,然后将请求转发到该页面
		mv.addObject("mockHouses", houseService.findHousesInterested(userName));
		mv.setViewName("houses.jsp?userName=" + userName);
		return mv;
	}
	@GetMapping("/house-details.action")
	public ModelAndView getHouseDetails(String userName, String houseId) {
		// 这里需要验证用户是否登录,省略
		ModelAndView mv = new ModelAndView();
		//查找房源详情并绑定到相应JSP页面,然后将请求转发到该页面
		mv.addObject("target", houseService.findHouseById(houseId));
		mv.setViewName("house-details.jsp?userName=" + userName);
		return mv;
	}
	@GetMapping("/house-form.action")
	public ModelAndView getHouseForm(String userName, String houseId) {
		// 这里需要验证用户是否登录,省略
		ModelAndView mv = new ModelAndView();
		//查找房源详情并绑定到相应JSP页面,然后将请求转发到该页面
		mv.addObject("target", houseService.findHouseById(houseId));
		mv.setViewName("house-form.jsp?userName=" + userName);
		return mv;
	}
	@PostMapping("/house-form.action")
	public ModelAndView postHouseForm(String userName, House house) throws UnsupportedEncodingException {
		// 这里需要验证用户是否登录,省略
		//更新指定房源的详情
		houseService.updateHouseById(house);
		//将请求转发到查找房源详情的动作
		ModelAndView mv = new ModelAndView();
		mv.setViewName("redirect:house-details.action?userName=" + userName + "&houseId=" + house.getId());
		return mv;
	}
}



Java代码 – 服务层

package houserenter.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import houserenter.entity.House;
@Service
public class HouseService {
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	@PostConstruct
	public void generateMockHouses() {
		jdbcTemplate.execute("drop table if exists house");
		jdbcTemplate.execute("create table house(id varchar(20) primary key, name varchar(100), detail varchar(500))");
		
		jdbcTemplate.update("insert into house values(?, ?, ?)", "1", "金科嘉苑3-2-1201", "详细信息");
		jdbcTemplate.update("insert into house values(?, ?, ?)", "2", "万科橙9-1-501", "详细信息");
	}
	
	public List<House> findHousesInterested(String userName) {
		// 这里查找该用户感兴趣的房源,省略,改为用模拟数据
		return jdbcTemplate.query(
				"select id,name,detail from house", 
				new HouseMapper());
	}
	public House findHouseById(String houseId) {
		return jdbcTemplate.queryForObject(
				"select id,name,detail from house where id = ?",
				new Object[]{houseId},
				new HouseMapper());
	}
	public void updateHouseById(House house) {
		jdbcTemplate.update(
				"update house set id=?, name=?, detail=? where id=?",
				house.getId(), house.getName(), house.getDetail(), house.getId());
	}
	
	private static final class HouseMapper implements RowMapper<House> {

		@Override
		public House mapRow(ResultSet rs, int rowNum) throws SQLException {
			return new House(rs.getString("id"), rs.getString("name"), rs.getString("detail"));
		}
		
	}
}



Java代码 – 实体类

package houserenter.entity;

public class House {

	private String id;
	private String name;
	private String detail;
	public House(String id, String name, String detail) {
		super();
		this.id = id;
		this.name = name;
		this.detail = detail;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDetail() {
		return detail;
	}
	public void setDetail(String detail) {
		this.detail = detail;
	}
	@Override
	public String toString() {
		return "House [id=" + id + ", name=" + name + ", detail=" + detail + "]";
	}
}



静态页面 – login.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>租房网 - 登录•</title>
</head>
<body>
	<form action="login.action" method="post">
		<label for="user_name">用户名</label><input type="text" id="user_name" name="userName" />
		<label for="password">密码</label><input type="password" id="password" name="password" />
		<input type="submit" value="登录•" />
	</form>
</body>
</html>



JSP页面

include.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.List" %>
<%@ page import="houserenter.entity.House" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>租房网</title>
</head>
<body>
<h1>你好,${param.userName}!欢迎来到租房网! <a href="login.html">退出</a></h1>
<br><br>

houses.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="include.jsp"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<h6>共找到你感兴趣的房源 ${mockHouses.size()} 条</h6>
<ul>
<c:forEach var="house" items="${mockHouses}">
	<li><h2><a href="house-details.action?userName=${param.userName}&houseId=${house.id}">${house.name}</a></h2></li>
</c:forEach>
</ul>
</body>
</html>

house-details.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="include.jsp"%>
<h2>${target.name}<a href="house-form.action?userName=${param.userName}&houseId=${target.id}">编辑</a></h2>
<h3>${target.detail}</h3>
<h4><a href="houses.action?userName=${param.userName}">回到列表</a></h4>
</body>
</html>

house-form.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="include.jsp"%>
<form action="house-form.action" method="post">
<input type="hidden" name="userName" value="${param.userName}"/>
<input type="hidden" name="id" value="${target.id}"/>
<label for="house_name">房源名字:</label><input type="text" id="house_name" name="name" value="${target.name}" />
<label for="house_detail">房源详细信息:</label><input type="text" id="house_detail" name="detail" value="${target.detail}" />
<input type="submit" value="提交" />
</form>
</body>
</html>