【Java项目脚手架系列】第二篇:JavaWeb项目脚手架

【Java项目脚手架系列】第二篇:JavaWeb项目脚手架

前言

在Java Web开发中,一个好的项目脚手架可以大大提高开发效率,减少重复工作。本篇文章将介绍一个基于Maven的JavaWeb项目脚手架,它包含了基础的Web开发配置和常用功能。

什么是JavaWeb项目脚手架?

JavaWeb项目脚手架是一个基于Maven的Web项目模板,它提供了:

  1. 标准的Web项目结构
  2. 基础的Web开发配置
  3. 常用功能组件
  4. 最佳实践示例

JavaWeb项目脚手架

1. 项目结构

javaweb-scaffold/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           ├── filter/
│   │   │           │   └── CharacterEncodingFilter.java
│   │   │           └── servlet/
│   │   │               ├── Error404Servlet.java
│   │   │               ├── Error500Servlet.java
│   │   │               └── HelloServlet.java
│   │   ├── resources/
│   │   │   └── log4j2.xml
│   │   └── webapp/
│   │       ├── WEB-INF/
│   │       │   └── web.xml
│   │       ├── error/
│   │       │   ├── 404.jsp
│   │       │   └── 500.jsp
│   │       └── index.jsp
│   └── test/
│       ├── java/
│       │   └── com/
│       │       └── example/
│       │           └── servlet/
│       │               └── HelloServletTest.java
│       └── resources/
├── docs/
│   └── 02-javaweb-scaffold.md
├── pom.xml
└── README.md

2. 核心文件内容

2.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.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.examplegroupId>
    <artifactId>javaweb-scaffoldartifactId>
    <version>1.0-SNAPSHOTversion>
    <packaging>warpackaging>

    <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <maven.compiler.source>1.8maven.compiler.source>
        <maven.compiler.target>1.8maven.compiler.target>
        <servlet.version>4.0.1servlet.version>
        <jsp.version>2.3.3jsp.version>
        <jstl.version>1.2jstl.version>
        <junit.version>5.8.2junit.version>
        <mockito.version>4.5.1mockito.version>
        <lombok.version>1.18.24lombok.version>
        <log4j2.version>2.17.2log4j2.version>
    properties>

    <dependencies>
        
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>javax.servlet-apiartifactId>
            <version>${servlet.version}version>
            <scope>providedscope>
        dependency>

        
        <dependency>
            <groupId>javax.servlet.jspgroupId>
            <artifactId>javax.servlet.jsp-apiartifactId>
            <version>${jsp.version}version>
            <scope>providedscope>
        dependency>

        
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>jstlartifactId>
            <version>${jstl.version}version>
            <scope>compilescope>
        dependency>

        
        <dependency>
            <groupId>org.junit.jupitergroupId>
            <artifactId>junit-jupiter-apiartifactId>
            <version>${junit.version}version>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>org.junit.jupitergroupId>
            <artifactId>junit-jupiter-engineartifactId>
            <version>${junit.version}version>
            <scope>testscope>
        dependency>

        
        <dependency>
            <groupId>org.mockitogroupId>
            <artifactId>mockito-coreartifactId>
            <version>${mockito.version}version>
            <scope>testscope>
        dependency>

        
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>${lombok.version}version>
            <scope>providedscope>
        dependency>

        
        <dependency>
            <groupId>org.apache.logging.log4jgroupId>
            <artifactId>log4j-apiartifactId>
            <version>${log4j2.version}version>
        dependency>
        <dependency>
            <groupId>org.apache.logging.log4jgroupId>
            <artifactId>log4j-coreartifactId>
            <version>${log4j2.version}version>
        dependency>
        <dependency>
            <groupId>org.apache.logging.log4jgroupId>
            <artifactId>log4j-slf4j-implartifactId>
            <version>${log4j2.version}version>
        dependency>
    dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-compiler-pluginartifactId>
                <version>3.8.1version>
                <configuration>
                    <source>${maven.compiler.source}source>
                    <target>${maven.compiler.target}target>
                configuration>
            plugin>
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-war-pluginartifactId>
                <version>3.3.2version>
            plugin>
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-surefire-pluginartifactId>
                <version>2.22.2version>
            plugin>
            <plugin>
                <groupId>org.apache.tomcat.mavengroupId>
                <artifactId>tomcat7-maven-pluginartifactId>
                <version>2.2version>
                <configuration>
                    <port>8080port>
                    <path>/javaweb-scaffoldpath>
                configuration>
            plugin>
        plugins>
    build>
project>
2.2 web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <display-name>JavaWeb Scaffolddisplay-name>

    
    <filter>
        <filter-name>characterEncodingFilterfilter-name>
        <filter-class>com.example.filter.CharacterEncodingFilterfilter-class>
        <init-param>
            <param-name>encodingparam-name>
            <param-value>UTF-8param-value>
        init-param>
    filter>
    <filter-mapping>
        <filter-name>characterEncodingFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

    
    <error-page>
        <error-code>404error-code>
        <location>/error/404.jsplocation>
    error-page>
    <error-page>
        <error-code>500error-code>
        <location>/error/500.jsplocation>
    error-page>
web-app>
2.3 CharacterEncodingFilter.java
package com.example.filter;

import javax.servlet.*;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter {
    private String encoding;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        encoding = filterConfig.getInitParameter("encoding");
        if (encoding == null) {
            encoding = "UTF-8";
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }
}
2.4 HelloServlet.java
package com.example.servlet;

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 java.io.IOException;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("Hello from JavaWeb Scaffold!");
    }
}
2.5 Error404Servlet.java
package com.example.servlet;

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 java.io.IOException;

@WebServlet("/error/404")
public class Error404Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        request.getRequestDispatcher("/error/404.jsp").forward(request, response);
    }
}
2.6 Error500Servlet.java
package com.example.servlet;

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 java.io.IOException;

@WebServlet("/error/500")
public class Error500Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        request.getRequestDispatcher("/error/500.jsp").forward(request, response);
    }
}
2.7 index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>



    
    JavaWeb Scaffold


    

Welcome to JavaWeb Scaffold

Click here to test the HelloServlet.

2.8 log4j2.xml

<Configuration status="WARN">
    <Properties>
        <Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%nProperty>
        <Property name="APP_LOG_ROOT">logsProperty>
    Properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="${LOG_PATTERN}"/>
        Console>
        <RollingFile name="FileAppender" 
                     fileName="${APP_LOG_ROOT}/app.log"
                     filePattern="${APP_LOG_ROOT}/app-%d{yyyy-MM-dd}-%i.log">
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="10MB"/>
            Policies>
            <DefaultRolloverStrategy max="10"/>
        RollingFile>
    Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="FileAppender"/>
        Root>
    Loggers>
Configuration>
2.9 404.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>



    
    404 - Page Not Found
    


    
404
Oops! The page you're looking for doesn't exist.
Return to Home
2.10 500.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>



    
    500 - Internal Server Error
    


    
500
Internal Server Error
An unexpected error occurred. Please try again later.
Return to Home
2.11 HelloServletTest.java
package com.example.servlet;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.StringWriter;

import static org.mockito.Mockito.*;

class HelloServletTest {
    @Mock
    private HttpServletRequest request;
    
    @Mock
    private HttpServletResponse response;
    
    private HelloServlet servlet;
    private StringWriter stringWriter;
    private PrintWriter writer;

    @BeforeEach
    void setUp() throws Exception {
        MockitoAnnotations.openMocks(this);
        servlet = new HelloServlet();
        stringWriter = new StringWriter();
        writer = new PrintWriter(stringWriter);
        when(response.getWriter()).thenReturn(writer);
    }

    @Test
    void doGet_ShouldWriteHelloMessage() throws Exception {
        // When
        servlet.doGet(request, response);

        // Then
        verify(response).setContentType("text/html;charset=UTF-8");
        writer.flush();
        assertTrue(stringWriter.toString().contains("Hello from JavaWeb Scaffold!"));
    }
}

3. 使用说明

  1. 环境准备

    • JDK 8+
    • Maven 3.6+
    • Tomcat 8.5+
  2. 克隆项目

    git clone [email protected]:zengqiang_wang/leecode-inteview-questions-journal.git
    
  3. 导入IDE

    • 推荐使用IntelliJ IDEA
    • 选择"Open as Maven Project"
  4. 运行项目

    mvn tomcat7:run
    

    访问:http://localhost:8080/javaweb-scaffold/

4. 最佳实践

  1. 项目结构

    • 遵循标准的Web项目结构
    • 合理划分包层次
    • 保持代码整洁
  2. 编码规范

    • 统一使用UTF-8编码
    • 使用字符编码过滤器
    • 规范JSP页面编码
  3. 错误处理

    • 配置统一的错误页面
    • 记录详细的错误日志
    • 提供友好的错误提示
  4. 测试编写

    • 使用JUnit 5编写单元测试
    • 使用Mockito模拟Servlet环境
    • 测试覆盖核心功能

5. 常见问题

  1. IDEA社区版无Tomcat插件

    • 使用Maven插件运行
    • 安装Smart Tomcat插件
    • 配置Tomcat服务器
  2. 首页500错误

    • 检查JSTL依赖配置
    • 简化JSP页面内容
    • 配置错误页面
  3. 编码问题

    • 确保所有文件使用UTF-8编码
    • 配置字符编码过滤器
    • 检查JSP页面编码声明

6. 总结

这个JavaWeb项目脚手架提供了一个基础的Web开发环境,包含了常用的配置和功能。通过解决常见问题,我们可以快速搭建一个可用的Web项目。

7. 下期预告

下一期我们将介绍SpringMVC项目脚手架,它将基于本期项目进行扩展,添加Spring MVC相关功能,包括:

  • 标准的MVC架构
  • 统一响应处理
  • 统一异常处理
  • 参数校验
  • 文件上传
  • RESTful API支持

敬请期待!

你可能感兴趣的:(Java项目脚手架指南,java,开发语言)