使用Maven构建Web应用(下)

上篇account-service中已经封装了实现细节,所以接下来只要在此次基础上提供Web页面,并使用简单servlet,jsp与后台实现交互控制。以下是account-web模块的构成:

  • 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>
	<parent>
		<groupId>com.juvenxu.mvnbook.account</groupId>
		<artifactId>account-parent</artifactId>
		<version>1.0.0-SNAPSHOT</version>
	</parent>

	<artifactId>account-web</artifactId>
	<packaging>war</packaging>
	<name>Account Web</name>

	<dependencies>
		<dependency>
			<groupId>${project.groupId}</groupId>
			<artifactId>account-service</artifactId>
			<version>${project.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>
	</dependencies>
</project>

上述代码中,account-web的packaging元素值为war,表示这是一个Web项目,需要以war方式打包。account-web依赖于servlet-api和jsp-api这两个几乎所有Web项目都要依赖的包,它们为servlet和jsp的编写提供支持。这里依赖范围是provided,表示它们不会被打包到war中,这是因为几乎所有Web容器都会提供这两个类库,如果war包中重复出现,就会导致依赖冲突等问题。account-web还依赖于account-service和spring-web,前者为Web应用提供底层支持,后者为Web应用提供Spring的集成支持。

在一些Web项目中,可能会有finalName的配置。该元素用来标识项目生成的主构件名称,该元素默认值已在超级POM中设定,值为${project.artifactId}-${project.version}。我们可以通过<finalName>account</finalName>的配置修改主构件名称为account,之后项目生成的war包名称就会成为account.war,更方便部署。

  • 主代码部分

主代码包含了2个JSP页面和4个Servlet,分别是:

  1. signup.jsp:账户注册页面
  2. login.jsp:账户登陆页面
  3. CaptchaImageServlet:生成验证码图片的Servlet
  4. LoginServlet:处理账户注册请求
  5. ActivateServlet:处理账户激活
  6. LoginServlet

不过首先要在web.xml中配置Servlet,该文件位于src/main/webapp/WEB-INF/目录下。配置如下:

//web.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
	<display-name>Account Service</display-name>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			classpath:/account-persist.xml
			classpath:/account-captcha.xml
			classpath:/account-email.xml
			classpath:/account-service.xml
		</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<servlet>
		<servlet-name>CaptchaImageServlet</servlet-name>
		<servlet-class>com.juvenxu.mvnbook.account.web.CaptchaImageServlet</servlet-class>
	</servlet>
	<servlet>
		<servlet-name>ActivateServlet</servlet-name>
		<servlet-class>com.juvenxu.mvnbook.account.web.ActivateServlet</servlet-class>
	</servlet>
	<servlet>
		<servlet-name>LoginServlet</servlet-name>
		<servlet-class>com.juvenxu.mvnbook.account.web.LoginServlet</servlet-class>
	</servlet>
	<servlet>
		<servlet-name>SignUpServlet</servlet-name>
		<servlet-class>com.juvenxu.mvnbook.account.web.SignUpServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>CaptchaImageServlet</servlet-name>
		<url-pattern>/captcha_image</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>SignUpServlet</servlet-name>
		<url-pattern>/signup</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>ActivateServlet</servlet-name>
		<url-pattern>/activate</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>LoginServlet</servlet-name>
		<url-pattern>/login</url-pattern>
	</servlet-mapping>
</web-app>

该web.xml首先配置了Web项目的显示名称,接着是一个名为ContextLoaderListener的ServletListener。该Listener来自于spring-web,用来为Web项目启动Spring的IoC容器,从而实现Bean的注入。名为contextConfigLocation的caontext-param则用来为指定的Spring配置文件的位置。这里的值是四个模块的Spring配置XML文件,例如classpath:/account-persist.xml表示从classpath的根路径获取名为account-persist.xml的文件。我们知道account-persist.xml文件在account-persist模块打包后的根路径下,这一JAR文件通过依赖的方式被引入到account-web的classpath下。web.xml中的其余部分是Servlet,包括各个Servlet的名称,类名以及相应的URL模式。

下面再构建视图文件signup.jsp文件,用来显示账户注册页面,存放在src/main/webapp/目录下。

<%@ page language="java" pageEncoding="UTF-8"
	contentType="text/html; charset=UTF-8"%>
<%@ page
	import="org.springframework.web.context.support.WebApplicationContextUtils"%>
<%@ page import="org.springframework.web.context.WebApplicationContext"%>
<%@ page import="org.springframework.context.ApplicationContext"%>
<%@ page import="com.juvenxu.mvnbook.account.service.*"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://"
			+ request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>

<!DOCTYPE html>
<html>
<head>
<base href="<%=basePath%>">
<title>SignUp Page</title>

<style type="text/css">
.text-field {
	position: absolute;
	left: 40%;
	background-color: rgb(255, 230, 220);
}

label {
	display: inline-table;
	width: 90px;
	margin: 0px 0px 10px 20px;
}

input {
	display: inline-table;
	width: 150px;
	margin: 0px 20px 10px 0px;
}

img {
	width: 150px;
	margin: 0px 20px 10px 110px;
}

h2 {
	margin: 20px 20px 20px 40px;
}

button {
	margin: 20px 20px 10px 110px
}
</style>
</head>

<body>
	<%
		//引入Spring的ApplicationContext类
		ApplicationContext context = WebApplicationContextUtils
				.getWebApplicationContext(getServletContext());
		//加载后台的AccountService对象
		AccountService accountService = (AccountService) context
				.getBean("accountService");
		//使用该对象生成一个验证码的key
		String captchaKey = accountService.generateCaptchaKey();
	%>
	<div class="text-field">

		<h2>注册新账户</h2>
		<form name="signup" action="signup" method="post">
			<label>账户ID:</label>
			<input type="text" name="id"/><br/>
			<label>Email:</label>
			<input type="text" name="email"/><br/>
			<label>显示名称:</label>
			<input type="text" name="name"/><br/>
			<label>密码:</label>
			<input type="password" name="password"/><br/>
			<label>确认密码:</label>
			<input type="password" name="confirm_password"/><br/>
			<label>验证码:</label>
			<input type="text" name="captcha_value"/><br/>
			<input type="hidden" name="captcha_key" value="<%=captchaKey%>"/>
			<img src="<%=request.getContextPath()%>/captcha_image?key=<%=captchaKey%>"/><br/>
			<button>确认并提交</button>
		</form>
	</div>
</body>
</html>

上述JSP中使用/captcha_image这一资源获取验证码图片。根据web.xml,该资源对应于CaptchaImageServlet,所有Servlet都放在src/main/java/目录下,代码如下:

//CaptchaImageServlet.java

package com.juvenxu.mvnbook.account.web;

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.juvenxu.mvnbook.account.service.AccountService;
import com.juvenxu.mvnbook.account.service.AccountServiceException;

@SuppressWarnings("serial")
public class CaptchaImageServlet extends HttpServlet {
	private ApplicationContext context; // Spring的ApplicationContext

	@Override
	/**
	 * 首先初始化ApplicationContext
	 */
	public void init() throws ServletException {
		super.init();
		context = WebApplicationContextUtils
				.getWebApplicationContext(getServletContext());
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 获取key参数
		String key = request.getParameter("key");
		// 检查key是否为空
		if (key == null || key.length() == 0) {
			// 返回HTTP400错误,请求不合法
			response.sendError(400, "No Captcha Key Found");
		} else {
			// 获取Spring Bean并强制类型转换
			AccountService service = (AccountService) context
					.getBean("accountService");

			try {
				// 设置response格式为image/jpeg
				response.setContentType("image/jpeg");
				// 将产生的字节流写入到Servlet的输出流中
				OutputStream out = response.getOutputStream();
				out.write(service.generateCaptchaImage(key));
				out.close();
			} catch (AccountServiceException e) {
				response.sendError(400, e.getMessage());
			}
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}
}

而signup.jsp中form表单的action是signup,根据web.xml对应于SignUpServlet,代码如下:

//SignUpServlet.java

package com.juvenxu.mvnbook.account.web;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.juvenxu.mvnbook.account.service.AccountService;
import com.juvenxu.mvnbook.account.service.AccountServiceException;
import com.juvenxu.mvnbook.account.service.SignUpRequest;

@SuppressWarnings("serial")
public class SignUpServlet extends HttpServlet {
	private ApplicationContext context; // 用于获取Spring Bean

	@Override
	/**
	 * 首先初始化ApplicationContext
	 */
	public void init() throws ServletException {
		super.init();
		context = WebApplicationContextUtils
				.getWebApplicationContext(getServletContext());
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// 获取HTTP POST请求,读取表单中的id,邮箱,用户名,密码,确认密码,验证主键,验证值参数
		String id = req.getParameter("id");
		String email = req.getParameter("email");
		String name = req.getParameter("name");
		String password = req.getParameter("password");
		String confirmPassword = req.getParameter("confirm_password");
		String captchaKey = req.getParameter("captcha_key");
		String captchaValue = req.getParameter("captcha_value");
		// 判断各参数是否为空,存在为空值则返回报错
		if (id == null || id.length() == 0 || email == null
				|| email.length() == 0 || name == null || name.length() == 0
				|| password == null || password.length() == 0
				|| confirmPassword == null || confirmPassword.length() == 0
				|| captchaKey == null || captchaKey.length() == 0
				|| captchaValue == null || captchaValue.length() == 0) {
			resp.sendError(400, "Parameter Incomplete.");
			return;
		}
		// 获取名为accountService的bean
		AccountService service = (AccountService) context
				.getBean("accountService");
		// 初始化一个SignUpRequest实例并设置其属性
		SignUpRequest request = new SignUpRequest();
		request.setId(id);
		request.setEmail(email);
		request.setName(name);
		request.setPassword(password);
		request.setConfirmPassword(confirmPassword);
		request.setCaptchaKey(captchaKey);
		request.setCaptchaValue(captchaValue);
		request.setActivateServiceUrl(getServletContext().getRealPath("/")
				+ "activate"); // 发送账户激活邮件的地址,这里是ActivateServlet的地址
		// 使用AccountService注册用户
		try {
			service.signUp(request);
			resp.getWriter()
					.print("Account is created, please check your mail box for activation link.");
		} catch (AccountServiceException e) {
			resp.sendError(400, e.getMessage());
			return;
		}
	}
}

在这里又用到了ActivateServlet,代码如下:

//ActivateServlet

package com.juvenxu.mvnbook.account.web;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.juvenxu.mvnbook.account.service.AccountService;
import com.juvenxu.mvnbook.account.service.AccountServiceException;

@SuppressWarnings("serial")
public class ActivateServlet extends HttpServlet {
	private ApplicationContext context;

	@Override
	public void init() throws ServletException {
		super.init();
		context = WebApplicationContextUtils
				.getWebApplicationContext(getServletContext());
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String key = req.getParameter("key");
		// 判断激活码是否为空
		if (key == null || key.length() == 0) {
			resp.sendError(400, "No activation key provided.");
			return;
		}
		AccountService service = (AccountService) context
				.getBean("accountService");
		// 激活账户
		try {
			service.activate(key);
			resp.getWriter().write("Account is activated, now you can login.");
		} catch (AccountServiceException e) {
			resp.sendError(400, "Unable to activate account");
			return;
		}
	}
}

以上是注册页面及相关逻辑处理的实现。另外一个页面是login.jsp,负责处理登录。

<%@ page contentType="text/html; charset=UTF-8" language="java"%>
<html>
<head>
<style type="text/css">
.text-field {
	position: absolute;
	left: 40%;
	background-color: rgb(255, 230, 220);
}

label {
	display: inline-table;
	width: 90px;
	margin: 0px 0px 10px 20px;
}

input {
	display: inline-table;
	width: 150px;
	margin: 0px 20px 10px 0px;
}

h2 {
	margin: 20px 20px 20px 40px;
}

button {
	margin: 20px 20px 10px 110px
}
</style>
</head>
<body>
	<div class="text-field">
		<h2>账户登录</h2>
		<form name="login" action="login" method="post">
			<label>账户ID:</label>
			<input type="text" name="id"/><br/>
			<label>密码:</label>
			<input type="password" name="password"/><br/>
			<button>确认并提交</button>
		</form>
	</div>
</body>
</html>

表单的action是login,LoginServlet代码如下:

//LoginServlet.java

package com.juvenxu.mvnbook.account.web;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.juvenxu.mvnbook.account.service.AccountService;
import com.juvenxu.mvnbook.account.service.AccountServiceException;

@SuppressWarnings("serial")
public class LoginServlet extends HttpServlet {
	private ApplicationContext context;

	@Override
	public void init() throws ServletException {
		super.init();
		context = WebApplicationContextUtils
				.getWebApplicationContext(getServletContext());
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String id = req.getParameter("id");
		String password = req.getParameter("password");

		if (id == null || id.length() == 0 || password == null
				|| password.length() == 0) {
			resp.sendError(400, "incomplete parameter");
			return;
		}

		AccountService service = (AccountService) context
				.getBean("accountService");

		try {
			service.login(id, password);
			resp.getWriter().print("Login Successful!");
		} catch (AccountServiceException e) {
			resp.sendError(400, e.getMessage());
		}
	}
}

由于代码格式及内容和上面的非常相似,所以这里省略了注释,大部分代码可以参考SignUpServlet。

最后在在src/main/resources/目录下建立一个配置文件,account-service.properties,具体配置参见前面邮箱的配置,示例如下

//account.service.properties

email.protocol=smtp
email.host=localhost
email.port=25
[email protected]
email.password=123456
email.auth=true
[email protected]
persist.file=C\:/persist-data.xml

这样一个maven的Web项目就构建完了。在account-web的目录上执行mvn clean install,该项目的WAR包就被打包到了本地仓库上。

参考书籍:《Maven实战》第12章——许晓斌著


版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-08 02:38:02

使用Maven构建Web应用(下)的相关文章

Eclipse使用Maven构建web项目

Eclipse使用Maven构建web项目 博客分类: J2EE 1.创建Maven项目: 点击“File”菜单,或者通过工具栏的“New”创建Project,如下图所示: 选择Maven->Maven Project,弹出向导对话框,如下图所示: 选中Create a simple project……复选框,其它的设置不变,并点击Next,输入maven项目必须的信息(groupId,artifactid,version),如下图所示: 这里需要选择Packaging,web项目一般选择war

利用Eclipse中的Maven构建Web项目(三)

利用Eclipse中的Maven构建Web项目 1.将Maven Project转换成动态Web项目,鼠标右键项目,输入"Project Facets" 2.根据Dynamic Web Module的版本修改Java Compiler中的"Compiler compliance level"的版本 3.设置部署程序集(Web Deployment Assembly),删除含有"test" 4.将Maven的jar包发布到lib下, "A

使用maven构建web项目

maven安装 1) 下载Maven:http://maven.apache.org/download.html 2) 解压缩下载的zip文件到本地目录下,比如:D:\Maven 3) 添加D:\Maven\bin到环境变量PATH中 4) 在命令行下运行mvn -version  或者 mvn –v查看是否安装成功 5) 安装eclipse插件 Eclipse Marketplace中搜索Maven Integration for Eclipse WTP并下载 为了使得Eclipse中安装的M

Maven的学习资料收集--(四)使用Maven构建Web项目-测试

2014-08-04 23:21 2人阅读 评论(0) 收藏 编辑 删除 目录(?)[+] [-] 在srcmainjava下新建一个Servlet 修改webxml 新建JSP 测试 在上一篇博客里,我们使用Maven构建了一个Web项目,我们在这里写一个简单的Servlet,测试一下. 1.在src/main/java下,新建一个Servlet [java] view plaincopyprint? <span style="font-weight: normal;">

Maven的学习资料收集--(三)使用Maven构建Web项目

新建Maven项目 File - New - Other 选择Maven Project 单击Next 保持默认即可单击Next 选择Archetype为 web app单击Next 输入一些必要信息单击Finish 项目结构如下图 配置项目 在项目上右键单击添加Source Folder 修改Build Path 配置 将项目转换为Dynamic Web Project 设置部署程序集Web Deployment Assembly 从网上查了一些资料,才算明白(也就是怎么操作吧),怎么使用Ma

Maven学习(三)- 使用Maven构建Web项目

从网上查了一些资料,才算明白(也就是怎么操作吧),怎么使用Maven构建一个Web项目,找到一篇文档,主要都是从这里学到的: 下载地址:使用Eclipse构建Maven的Web项目.docx 现自己在重新操作一下:(使用的是Eclipse JavaEE版 ps:eclipse-jee-indigo-SR1-win32,已经安装好了m2eclipse插件) 1.新建Maven项目 1.1 File -> New -> Other 1.2 选择Maven Project ,单击Next 1.3 保

利用Eclipse中的Maven构建Web项目(一)

利用Eclipse中的Maven构建Web项目 1.新建一个Maven Project,"New-->Other..." 2.选择"Maven Project" 3.选择项目路径 Usedefault Workspace location默认工作空间, 选择项目类型 在Artifact Id中选择maven-archetype-webapp 4.分别输入Group Id.Artifact Id和Package,单击"Finish" 5.Ma

利用Eclipse中的Maven构建Web项目(二)

利用Eclipse中的Maven构建Web项目 1.新建源文件夹,Java Resources鼠标右键,"New-->Source Folder" 2.新建src/main/java   src/main/resources  src/test/java  src/test/resources四个源包 3.双击每个文件夹的Output folder,选择路径 src/main/java和src/main/resources,选择路径target/classes; src/test

Maven构建Web工程项目报错

利用Maven构建Web项目的时候项目报错,pom.xml报错 先右键Maven-Disable Maven Nature,关闭Maven属性 然后再点击Configure-Convert To Maven Project 然后就能消除错误

利用Eclipse中的Maven构建Web项目报错

利用Eclipse中的Maven构建Web项目 1.在进行上述操作时,pom.xml一直报错 <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.o