通过一个单词本程序,记录javaWeb的基本流程
环境准备
| TOOLS | VERSION |
|---|---|
| Maven | 3.8.4 |
| MyBatis | 3.5.9 |
| MySQL | 8.0.28 |
| Tomcat | 10.0.8 |
| Servlet | 4.0.1 |
| JSP | 2.3.3 |
| JSTL | 1.2 |
| Taglibs | 1.2.5 |
使用Maven创建javaWeb项目结构
- 首先配置一下Maven的本地仓库
在..\apache-maven-3.8.4\conf\settings.xml中修改或添加标签<localRepository>..\apache-maven-3.8.4\repo</localRepository>,否则其默认的仓库位于c盘的..\用户\..\.m2\repository中。 - 配置阿里云的镜像仓库以便下载依赖
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
- maven web项目结构

下载依赖
在pom.xml文件中引入坐标以下载依赖
要使用JSTL需要导入JSTL与Taglibs两个坐标,并且要在JSP页面中通过标签引入<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>。Servlet与JSP的作用域scope为provided,是因为其在Tomcat中已经实现了,所以打包成war包后是不需要的。
此处有一个问题,在idea中使用maven时需要在idea里配置的,要选择引入哪里的maven配置文件,不然会使用默认的C盘里的配置文件,从而无法将jar包存入本地仓库。

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<!--这是正确的包-->
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!-- 下面这两个是错误的包 -->
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</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>
<scope>runtime</scope>
</dependency>
- 此外,还有一个Tomcat插件用以方便开发阶段的测试
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins
</build>
在idea中配置数据库
选择右边栏的Dadabase标签,点击加号选择MySQL,弹出界面,填写用户名和密码,以及要连接的数据库名称。点击Test Connection可以查看是否连接成功。

容易出现一个问题,及idea与MySQL的时区不同步,显示Go to ‘Advanced’ tab and set ‘serverTimezone‘ property manually的错误提示。则需要修改idea的时区,及点击Advanced标签,找到serverTimezone选项,填入"CST"。
配置MyBatis
首先要编写MyBatis的核心配置文件,即mybatis-config.xml文件。其配置的基本内容如以下代码所示。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/english_words?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="*****"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
其中,driver是jdbc驱动包名,url的格式为:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数名1=参数值1...,另外,如果连接本地mysql且端口号为默认的3306,则可以简写成jdbc:mysql:///数据库名称?参数名1=参数值1...,用户名与密码为mysql的用户名与密码。这之中的参数useSSL是一种加密的安全连接机制,设定为false可以避免警告提示。environments里可以配置多个environment,用来切换不同阶段的数据库源,如开发环境与测试环境所用的数据库源不一样。transactioinManager是用来处理事物的,之后会由Spring来代替。
另外,还要编写SQL的映射文件,用以统一管理SQL语句。
- 首先要在resources目录下创建一个mapper目录,并在目录里创建映射文件,此处为
WordsMapper.xml。
在映射文件中写如基本的配置信息,如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.WordsMapper">
<select id="selectAll" resultType="pojo.Words">
select * from words;
</select>
</mapper>
其中namespace是名称空间,id是该sql语句的唯一标识符,而resultType是返回结果的类型。
使用Mapper代理开发,用来解决硬编码问题,同时给予IDE代码自动补全的能力,提高效率
-
首先要定义与SQL映射文件同名的Mapper接口文件,并且将接口与映射文件放在同一目录下

-
设置SQL映射文件中的namespace属性为Mapper接口全限定名,如上的
namespace="mapper.WordsMapper" -
在Mapper接口文件中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致。接口中方法定义如下:
public interface WordsMapper {
List<Words> selectAll();
}
- 于是就可以在写代码时通过SqlSession的getMapper方法获取Mapper接口的代理对象,然后调用对应方法完成sql语句的执行。如下:
WordsMapper wordsMapper = sqlSession.getMapper(WordsMapper.class);
List<Words> words = WordsMapper.selectAll();
需要注意的是mybatis-config.xml文件中的mappers标签中需要注册<mapper resource="mapper/WordsMapper.xml"/>。
- 最后在mybatis-config.xml中进行typeAliases别名设置,别名设置可以扫描所有pojo目录下的实体类,并且不区分大小写,即
pojo.User可以写成user,当包名很长时,这样做是方便的。
<typeAliases>
<package name="pojo" />
</typeAliases>
//WordsMapper.xml文件中可以更改为
resultType="words"
以上,环境准备完成。
- 此时的
mybatis-config.xml文件内容为:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="pojo" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/english_words?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="*****"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/WordsMapper.xml"/>
</mappers>
</configuration>
- 此时,
WordsMapper.xml内容为
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.WordsMapper">
<select id="selectAll" resultType="words">
select * from words;
</select>
</mapper>
创建MVC项目结构

- mapper目录中存放sql映射的接口文件
- pojo目录中存放实体类,并包含getter&setter,和toString方法
- service目录是MVC中的逻辑处理层,负责组合数据
- util目录是存放工具包
- web目录是controller层,负责控制
- resources目录中存放配置文件以及一些图片等,当maven打包后会和java放在一起,同目录名会被放在同一目录下。
- webapp存放web配置文件以及html和jsp等。
MVC实现

-
实现DAO层,需要编写sql映射文件WordsMapper.xml和定义接口文件WordsMapper的selectAll方法。上述已实现。
-
编写sqlSessionFactory工具类,用以避免重复的代码,且SqlSessionFactory工厂只需要创建一次,不要重复创建,所以可以通过静态代码块来解决,因为静态代码块随着类的加载只会执行一次。
首先要明确调用Sql映射的步骤:
-
读取mybtis-config.xml配置文件
-
通过配置信息构建工厂类
-
通过openSession()方法获取sqlSession对象
-
通过sqlSession.getMapper(WordsMapper.class)获取WordsMapper接口类型对象
-
通过调用wordsMapper.selectAll()方法执行SQL
-
最后要记得关闭连接,sqlSession.close()
-
以下代码的工厂类只执行了一次,每一次返回的都是同一个对象。
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class SqlSessionFactoryUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
String resource = "mybatis-config.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSessionFactory() {
return sqlSessionFactory;
}
}
- 实现Service层,其步骤已在上一点说明
public class WordsService {
public List<Words> selectAll() {
//调用WordsMapper.selectAll()方法
SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
WordsMapper wordsMapper = sqlSession.getMapper(WordsMapper.class);
List<Words> words = wordsMapper.selectAll();
sqlSession.close();
return words;
}
}
- 实现controller(Web)层,编写servlet的代码
- 首先要调用Service层完成查询,service对象的创建需要多次用到,所以应放在方法外
- 然后将查询结果存入request域中
- 最后转发到一个JSP中处理,需要理解的是,JSP其实是一个Servlet文件,通过Tomcat将JSP转译成Sevlet文件,其实际代码是由write方法一行行将html代码写入,其中包含了从数据库中取出的数据,称之为动态。
@WebServlet("/selectAllServlet")
public class SelectAllServlet extends HttpServlet {
private WordsService wordsService = new WordsService();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<Words> words = wordsService.selectAll();
req.setAttribute("words", words);
req.getRequestDispatcher("/words.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
- HttpServlet是Servlet的实现类,封装了对http协议的解析方法
- 编写words.jsp文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>记单词</title>
</head>
<body>
<table>
<tr>
<th>序号</th>
<th>英文</th>
<th>中文</th>
</tr>
<c:forEach items="${words}" var="word">
<tr>
<td>${word.id}</td>
<td>${word.english}</td>
<td>${word.chinese}</td>
</tr>
</c:forEach>
</table>
<h1>${words}</h1>
</body>
</html>
- 此处在运行时遇到一个问题,就是导错了jstl和taglibs的jar包,然后就会报错:
java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/LoopTag,这个错误就是由于jstl包导错的原因,jstl在maven上有好几个分不清,应该是如下:
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
- 写一个index.html文件,内容为
<a href="/EnglishWords/selectAllServlet">查询所有</a>
运行
测试时可以利用maven的插件tomcat7: 
或者mvn package打包,将其war包放入Tomcat目录中的webapps目录下,启动Tomcat即可在localhost:8080/EnglishWords下访问。
- 这里遇到了一个很坑的问题,Tomcat10版本和Servlet版本是不兼容的,如果将war包放在版本是10的Tomcat中就会出现如下的404和服务器500的问题,解决的办法就是把Tomcat10换成Tomcat8:

或者

总结
效果:

遇到了很多问题,记录下来,整个javaWeb的流程基本了解。

浙公网安备 33010602011771号