Maven
Maven的作用:
- 标准化的项目结构
- 标准化的项目构建流程(编译-测试-打包-发布)
- 依赖管理机制
仓库
- 本地仓库:自己计算机上的一个目录
- 中央仓库:由Maven团队维护的全球唯一的仓库
- 远程仓库(私服):一般由公司团队搭建的私有仓库
- 生命周期
- clean :清理工作。
- default :核心工作,例如编译,测试,打包,安装等。
- site : 产生报告,发布站点等。这套声明周期一般不会使用。
- Maven坐标
- groupId:定义当前Maven项目隶属组织名称(通常是域名反写,例如:com.itheima)
- artifactId:定义当前Maven项目名称(通常是模块名称,例如 order-service、goods-service)
- version:定义当前项目版本号
idea 中导入Maven项目:双击pom.xml
依赖管理
在 pom.xml 中 按 alt + insert,选择 Dependency
依赖范围
依赖范围 | 编译classpath | 测试classpath | 运行classpath | 例子 |
---|---|---|---|---|
compile | Y | Y | Y | logback |
test | - | Y | - | Junit |
provided | Y | Y | - | servlet-api |
runtime | - | Y | Y | jdbc驱动 |
system | Y | Y | - | 存储在本地的jar包 |
Mybatis
- 作用:
一款优秀的持久层框架,用于简化JDBC开发
- JDBC的缺点 && Mybatis如何优化
- 硬编码 (Mybatis可以配置到==配置文件==)
1 注册驱动、获取连接
2 SQL语句
- 操作繁琐(Mybatis都==自动完成==)
3 手动设置参数
4 手动封装结果集
- Mapper代理开发
- 准备工作
- 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下。如下图:
- 准备工作
2. 设置SQL映射的配置文件(上图中的UserMapper.xml)的namespace属性为Mapper接口全限定名
3. 在 Mapper 接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
- 代码实现
- 在
com.itheima.mapper
包下创建 UserMapper接口,代码如下:public interface UserMapper {
List<User> selectAll();
User selectById(int id);
}
- 在
resources
下创建com/itheima/mapper
目录(directory),并在该目录下创建 UserMapper.xml 映射配置文件<!--
namespace:名称空间。必须是对应接口的全限定名
-->
<mapper namespace="com.itheima.mapper.UserMapper">
<select id="selectAll" resultType="com.itheima.pojo.User">
select *
from tb_user;
</select>
</mapper>
在
com.itheima
包下创建 MybatisDemo2 测试类,代码如下:/**
* Mybatis 代理开发
*/
public class MyBatisDemo2 {
public static void main(String[] args) throws IOException {
//1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 执行sql
//3.1 获取UserMapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.selectAll();
System.out.println(users);
//4. 释放资源
sqlSession.close();
}
}
注意:
如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载。也就是将核心配置文件的加载映射配置文件的配置修改为
<mappers>
<!--加载sql映射文件-->
<!-- <mapper resource="com/itheima/mapper/UserMapper.xml"/>-->
<!--Mapper代理方式-->
<package name="com.itheima.mapper"/>
</mappers>
Tomcat
绿色版,直接解压
在idea中配置(两种方法)
- 本地 local 配置,找到tomcat的位置,并且部署
- 在pom.xml文件中配置tomcat7-maven-plugin插件
小坑:解决80端口已经被占用的情况:在命令行中通过netstat -ano找到80端口被哪个线程占用了,在任务管理器中释放掉
流程:
- 用maven的骨架(archetype)构建一个webapp项目,添加java目录和resources目录,至此完成一个maven-web项目的创建
- 配置tomcat
- 方法1:local
找到tomcat应用程序所在目录:
部署:
- 方法2 插件
Servlet
- Servlet是JavaEE13项规范中的其中一项,是一个接口
| Modifier and Type | Method and Description |
| —- | —- |
| void | destroy()
Called by the servlet container to indicate to a servlet that the servlet is being taken out of service. | | ServletConfig | getServletConfig()
Returns a ServletConfig object, which contains initialization and startup parameters for this servlet. | | String | getServletInfo()
Returns information about the servlet, such as author, version, and copyright. | | void | init(ServletConfig config)
Called by the servlet container to indicate to a servlet that the servlet is being placed into service. | | void | service(ServletRequest req, ServletResponse res)
Called by the servlet container to allow the servlet to respond to a request. |
以上方法都需要重写
- 执行流程
servlet对象由tomcat web服务器创建,servlet方法也由tomcat web服务器调用
- Servlet对象的生命周期 :4个阶段(Servlet运行在Servlet容器(web服务器)中,其生命周期由容器来管理)
- ==加载和实例化==:默认情况下,当Servlet第一次被访问时,由容器创建Servlet对象
- ==初始化==:在Servlet实例化之后,容器将调用Servlet的 init() 方法初始化这个对象,完成一些如加载配置文件、创建连接等初始化的工作。
该方法只==调用一次==
- ==请求处理==:每次请求Servlet时,Servlet容器都会调用Servlet的service()方法对请求进行处理
==调用多次==
- ==服务终止==:当需要释放内存或者容器关闭时,容器就会调用Servlet实例的==destroy()==方法完成资源的释放。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收
==调用一次==
- Servlet体系结构
开发B/S架构的web项目,都是针对HTTP协议,所以我们自定义Servlet,会通过继承==HttpServlet==
需要重写doGet和doPost方法
@WebServlet("/demo4")
public class ServletDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//TODO GET 请求方式处理逻辑
System.out.println("get...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//TODO Post 请求方式处理逻辑
System.out.println("post...");
}
}
request对象
- get方法和post方法获取请求参数的通用方式
由于get方法和post方法一个是从请求头拿数据一个是从请求体,因此操作不一样,但是重复实现会有相同的代码,因此——>
解决方案一:
在doget方法中进行get和post逻辑判断,让dopost方法去调用doget
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求方式
String method = req.getMethod();
//获取请求参数
String params = "";
if("GET".equals(method)){
params = req.getQueryString();
}else if("POST".equals(method)){
BufferedReader reader = req.getReader();
params = reader.readLine();
}
//将请求参数进行打印控制台
System.out.println(params);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
但是以后每个Servlet都需要这样写代码,实现起来比较麻烦,这种方案我们不采用
解决方案二:
request对象为我们提供了如下方法:
//获取所有参数Map集合
Map<String,String[]> getParameterMap()
//根据名称获取参数值(数组)
String[] getParameterValues(String name)
//根据名称获取参数值(单个值)
String getParameter(String name)
- 所以可以首先在doGet方法中实现:
在Servlet代码中获取页面传递GET请求的参数值
/**
* 获取请求参数
*/
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//GET请求逻辑
System.out.println("get....");
//1. 获取所有参数的Map集合
Map<String, String[]> map = req.getParameterMap();
for (String key : map.keySet()) {
// username:zhangsan lisi
System.out.print(key+":");
//获取值
String[] values = map.get(key);
for (String value : values) {
System.out.print(value + " ");
}
System.out.println();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
///获取GET请求参数中的爱好
String[] hobbies = req.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
//获取GET请求参数中的用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username);
System.out.println(password);
- 在Servlet代码中获取页面传递POST请求的参数值
将req.html页面form表单的提交方式改成post
将doGet方法中的内容复制到doPost方法中即可
小结:模板
public class RequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//采用request提供的获取请求参数的通用方式来获取请求参数
//编写其他的业务代码...
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
- request请求转发
req.getRequestDispatcher("资源B路径").forward(req,resp);//由于服务器内部转发,所以不需要加虚拟目录(项目访问路径)
特点:
- 浏览器地址栏路径不发生变化虽然后台从/req5转发到/req6,但是浏览器的地址一直是/req5,未发生变化
- 只能转发到当前服务器的内部资源不能从一个服务器通过转发访问另一台服务器
- 一次请求,可以在转发资源间使用request共享数据虽然后台从/req5转发到/req6,但是只有一次请求
response对象
- response提供的方法 设置响应行、响应头、响应体 ```java //响应行 设置状态码 void setStatus(int sc);
//响应头 设置键值对 void setHeader(String name,String value);
//响应体 //获取字符输出流: PrintWriter getWriter(); //获取字节输出流 ServletOutputStream getOutputStream();
2. 资源**重定向**
![image.png](https://cdn.nlark.com/yuque/0/2022/png/26312519/1649661587521-aa616136-8eb0-4f79-8e34-72a0f627da73.png#clientId=uccf495bc-3231-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=270&id=udd9632ef&margin=%5Bobject%20Object%5D&name=image.png&originHeight=337&originWidth=1368&originalType=binary&ratio=1&rotation=0&showTitle=false&size=110411&status=done&style=none&taskId=u636d1412-b4a7-4d11-87c6-d31f69d7c7c&title=&width=1094.4)
```java
@WebServlet("/resp1")
public class ResponseDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("resp1....");
//重定向 需要加项目路径/request-demo
resposne.sendRedirect("/request-demo/resp2");
//`/request-demo`是固定编码的,如果tomcat插件配置了项目访问路径很麻烦,所以应该动态去获取项目访问的虚拟目录
String contextPath = request.getContextPath();
response.sendRedirect(contextPath+"/resp2");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
特点(对比request):
- 浏览器地址栏路径发送变化当进行重定向访问的时候,由于是由浏览器发送的两次请求,所以地址会发生变化
- 可以重定向到任何位置的资源(服务内容、外部均可)因为第一次响应结果中包含了浏览器下次要跳转的路径,所以这个路径可以是任意位置资源。
- 两次请求,不能在多个资源使用request共享数据因为浏览器发送了两次请求,是两个不同的request对象,就无法通过request对象进行共享数据
response响应数据
- 字符数据 ```java /**
- 响应字符数据:设置字符数据的响应体 */ @WebServlet(“/resp3”) public class ResponseDemo3 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(“text/html;charset=utf-8”); //1. 获取字符输出流 PrintWriter writer = response.getWriter(); writer.write(“aaa”); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } } ```
- 字节数据
方法1:
/**
* 响应字节数据:设置字节数据的响应体
*/
@WebServlet("/resp4")
public class ResponseDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 读取文件
FileInputStream fis = new FileInputStream("d://a.jpg");
//2. 获取response字节输出流
ServletOutputStream os = response.getOutputStream();
//3. 完成流的copy
byte[] buff = new byte[1024];
int len = 0;
while ((len = fis.read(buff))!= -1){
os.write(buff,0,len);
}
fis.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
方法2
(1)pom.xml添加依赖
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
(2)调用工具类方法
//fis:输入流
//os:输出流
IOUtils.copy(fis,os);
@WebServlet("/resp4")
public class ResponseDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 读取文件
FileInputStream fis = new FileInputStream("d://a.jpg");
//2. 获取response字节输出流
ServletOutputStream os = response.getOutputStream();
//3. 完成流的copy
IOUtils.copy(fis,os);
fis.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
demo
小坑:mysql依赖的版本号 不对的话会报500
项目结构
DAO层
Service层
Web层