javaweb
[toc]
JavaWeb
1.编写Servlet
重要补充:request是从服务器获取数据,response是从服务器向浏览器返回数据
通过配置的maven新建
webapp模板工程并且配置pom.xml文件(是mvn的核心文件)来导入Servlet的依赖<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency>1
2
3
4
5
6
7
- 创建一个类继承HttpServlet,并重写Service方法
- ```java
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
res.getWriter().write("Hello servlet");//通过浏览器窗口输出Hello servlet
}
在web.xml里编写映射
这里注意检查web.xml的版本,最好不要太旧
可以直接复制这个xml粘贴(虽然不是很新,但是也不是太旧hh)
<?xml version="1.0" encoding="UTF-8"?> <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_3_1.xsd" version="3.1" metadata-complete="true"> </web-app>1
2
3
4
5
6
7
8
- 分别是两个标签的实现:servlet和servlet-mapping(是写在webapp这个大标签里的)
- ```xml
<servlet></servlet> 在向servlet或JSP页面制定初始化参数或定制URL时,必须首先命名servlet或JSP页面。Servlet元素就是用来完成此项任务的。
<servlet-mapping></servlet-mapping> 服务器一般为servlet提供一个缺省的URL:
<!--http://host/webAppPrefix/servlet/ServletName.这里就缺省了后面的url-->
但是,常常会更改这个URL,以便servlet可以访问初始化参数或更容易地处理相对URL。在更改缺省URL时,使用servlet-mapping元素。
<servlet> <servlet-name>HelloServlet</servlet-name><!--注册servlet--> <servlet-class>HelloServlet</servlet-class><!--这个是文件的相对位置--> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name><!--与上面的servletname需要一致--> <url-pattern>/cf</url-pattern><!--填写重定向后的地址--> </servlet-mapping>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- 启动tomcat服务器
- 在idea的右上角选择本地的tomcat服务器,找到Deployment的选项窗口添加war包的位置
- Application context是浏览器通过localhost:8080端口启动后的位置
- 
- 通过localhost:8080加上Deployment窗口加上servlet的重定向来访问
- 
- 补充:关于mapping
- 一个servlet映射一个路径->只有访问指定的路径才可以得到信息
- ```xml
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/cf</url-pattern>
</servlet-mapping>一个servlet映射多个路径->只有其他的路径也可以得到信息
<!--这里通过cf1,cf2,cf都可以访问到原来的hello servlet--> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/cf</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/cf1</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/cf2</url-pattern> </servlet-mapping>1
2
3
4
5
6
7
8
9
- 一个servlet可以指定通用映射路径(利用通配符*来解决)
- ```xml
<!--这时候也是不会进index.jsp,优先级相对高-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/cf/*</url-pattern>
</servlet-mapping>
自定义后缀实现请求映射
<!--这时候利用do后缀就可以进入 但是前面不能加上任何路径 --> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>1
2
3
4
5
6
7
8
9
10
11
12
13
14
### 2.ServletContext
1. 解释:每一个web应用都有且仅有一个ServletContext对象,又称Application对象,从名称中可知,该对象是与应用程序相关的。在WEB容器启动的时候,会为每一个WEB应用程序创个对应的ServletContext对象。
2. 作用
- **共享数据**,可以通过一方来保存,另一方可以读取
3. 两个小方法:
- ```java
getServletContext//设置储存的信息,以键值对的形式
getAttribute//获取储存的信息,需要键的名为对象
具体实现:
public class Hello02 extends HttpServlet {//添加类 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset = utf-8"); ServletContext context = this.getServletContext();//获取context对象 String name = "借口"; context.setAttribute("username", name);//设置添加的字符串,以键值对的形式 System.out.println("添加成功"); } } public class getC extends HttpServlet {//获取类 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); ServletContext context = this.getServletContext();//同样是获取context对象,因为是全局的的,所以能找到里面所有的信息 String username = (String) context.getAttribute("username");//以键名的形式获取 resp.getWriter().write(username); } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
5. 配置web.xml
6. 启动tomcat服务器分别访问两个类
### 3.请求转发
- 不改变原来的地址,但是能够改变跳转的位置
- 相当于是有三个人A,B,C ;A想要给C传达消息,但是A只能联系到B,而B作为传话筒将A的信息传给C,同样的C的信息也通过B传给了A,请求转发的作用就是B角色
- ```java
ServletContext context = this.getServletContext();//先获取context对象
context.getRequestDispatcher("/cf").forward(req,resp);//调用getRequestDispatcher方法输入请求转发的地址,以及请求出去需要发送的req,resp->这样就可以将地址传给web.xml里的cf地址来跳转,然后将req,resp同时转给cf的地址
4.通过Servletcontext读取配置文件
先创建一个ServletContext对象;调用
getResourceAsStream方法将文件转化成流创建properties对象加载流,并获取信息
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); Properties prop = new Properties(); InputStream ras = context.getResourceAsStream("/WEB-INF/classes/db.properties"); prop.load(ras); String username = prop.getProperty("username"); String pwd = prop.getProperty("password"); resp.getWriter().write(username+":"+pwd); }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
- 注意事项:(一定要写相对路径)现在写的类同时会产生class类,同样的properties配置文件也是在class下,而本类写的东西是要在同类的地方产生class->即现在要找的配置文件就是本类的WEB-INF的classes下面
### 5.Response
从浏览器来的就叫request的呗,从我这边走出去的就叫response呗
#### 1.下载
1. 找到文件的地址,通过io流读写,并通过response的`getOutputStream`方法来写入
2. 设置response的Header声明出是下载文件
- ```java
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String realPath = "D:\\project\\java\\execrise\\project02\\src\\main\\resources\\a.jpg";
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
resp.setHeader("Content-Disposition", "attachment;filename=" +fileName );//最重要的设置头,表明下载
FileInputStream fis = new FileInputStream(realPath);
ServletOutputStream os = resp.getOutputStream();//获取流去读写
byte[] buffer = new byte[1024];
int len ;
while((len = fis.read(buffer))!=-1){
os.write(len);
}
os.close();
fis.close();
}
2.重定向
还是有ABC三个人,A想要获取信息,他一开始只能找到B,接着B告诉A他需要的信息是在C那边,然后A就去找C,重定向就相当于是A从B询问后找C的过程。
用途:用户登录
主要方法
Send Redirectpublic class Demo02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.sendRedirect("/cf/demo03");//重定向的地址 //实际实现就是设置新地址和新的状态码 } } //注意:重定向时候需要注意重定向的路径地址,是不是要加上Application context的位置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- 特点:地址会发生变化
### 6.Request与前端的连接测试
#### 6.1表单的简单提交
- 利用jsp编写表单
- ```jsp
<html>
<body>
<h2>Hello World!</h2><br>
<form action="${pageContext.request.contextPath}/demo06" method="get">
用户名:<input type="text" name="username"> <br>
密码 :<input type="password" name="password"><br>
<input type="submit">
</form>
</body>
</html>
<%--${pageContext.request.contextPath}/demo06这个是用来与后端的服务器相连的信息,结果就会走demo06的网络路径 要提前导maven--%>
编写对应的java后台服务
public class Demo06 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("进入了这个服务"); String username = req.getParameter("username");//获取username信息 String password = req.getParameter("password");//获取password信息 System.out.println(username+":"+password); } } //getParameter就是用来获取特定的字段中信息的具体内容的1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
### 7.Cookies
- 作用
- 保存登录数据
- 编写一个小的Cookie访问
- ```java
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset = utf-8");//设置服务器返回编码
Cookie[] cookies = req.getCookies();//先获取cookies
PrintWriter writer = resp.getWriter();//浏览器输出
boolean flag =false;
for (Cookie cookie : cookies) {
if (cookie.getName().equals("lastTime")){
Long timer = Long.valueOf(cookie.getValue());//还原原来的日期格式
Date date = new Date(timer);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
String currentTime = sdf.format(date);
writer.write("你上一次访问本站的时间是:"+currentTime);
flag =true;
}
}
if (!flag) writer.write("这是你第一次访问,我们为您创建了cookie,方便下次访问");
Cookie lastTime = new Cookie("lastTime", System.currentTimeMillis() + "");//Cookie都是以键值对的形式存在
resp.addCookie(lastTime);
}
注销Cookie
- 手动调用
setMaxAge设置时间为0
- 手动调用
8.Session
作用:
- 还是暂存用户信息,如登录信息,但是更强大,能存储整个类,同时存储容量上限也高
编写一个存储person类的session例
person类
String name; int age ; //构造函数,get,set,tostring1
2
3
4
5
6
7
8
9
10
- 创建Session的类
- ```java
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset = utf-8");
HttpSession session = req.getSession();
session.setAttribute("username", new Person("借口",18));
}
得到session的类
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset = utf-8"); HttpSession session = req.getSession(); Person person = (Person) session.getAttribute("username"); System.out.println(person); resp.getWriter().write(String.valueOf(person)); }1
2
3
4
5
6
7
8
9
10
11
- 先调用第一个类,然后调用第二个类就可以获取到存储到整个类里的信息了
- Session的注销
- 调用`invalidate`方法手动注销
- ```xml
<session-config>
<session-timeout>1</session-timeout><!--这里就是配置session的注销时间,以分钟为单位-->
</session-config>
Session和Cookie的区别
- Cookie是把用户的数据写给用户的浏览器,浏览器保存
- Session把用户的数据写到用户独占Session中,服务器保存(保存重要的信息,减少服务器资源的浪费)
- Session对象由服务创建
9.JSP
9.1Jsp语法
整个JSP的内容实际上是一个HTML,但是稍有不同:
- 包含在
<%--和--%>之间的是JSP的注释; - 包含在
<%和%>之间的是Java代码,可以编写任意Java代码; - 如果使用
<%= xxx %>则可以快捷输出一个变量的值。 <%! %>可以写java代码(作用域更高的,相当于全局),称之为声明:会被编译到SP生成ava的类中!其他的,就会被生成到jspService方法中!
9.2定义跳转错误页面
1 | <error-page> |
9.3包含相同的标签头和尾
1 | <jsp:include page="index.jsp"/><%--这里就像人家的公安机关的声明,是重复可用的可以包含导入--%> |
9.4内置9大对象
1 | PageContext <%--存东西,级别最次--%> |
9.5 jsp表达式标签
1 | <%-- <jsp:include page=""/>--%> |
9.6Jstl常用
- if,switch,set;
1 | <form action="JstlTest01.jsp" method="get"> |
foreach
1 | <% |
10.Filter过滤器
编写fileterDemo类,实现Fileter接口(是javax.servlet包下面的Fileter)
public class FilterDemo01 implements Filter { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding("utf-8");//请求编码 servletResponse.setContentType("text/html;charset = utf-8");//响应编码 System.out.println("doFilter进入前面"); filterChain.doFilter(servletRequest,servletResponse);//主要方法,看成一条链,传递原来的req和resp对象; System.out.println("doFilter进入后面"); } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
- 配置web.xml
- 由于注册servlet的xml中url-pattern可以对应多个地址,所以如果可以通过不同的url-pattern来验证
- ```xml
<filter>
<filter-name>filterDemo</filter-name>
<filter-class>com.LeiLei.Demo01.FilterDemo01</filter-class>
</filter>
<filter-mapping>
<filter-name>filterDemo</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
11.Listener
先实现
HttpSessionListenerservlet监听器接口,重写方法;public void sessionCreated(HttpSessionEvent se) {//创建方法 ServletContext context = se.getSession().getServletContext(); Integer onlineCnt = (Integer) context.getAttribute("onlineCnt");//获取onlineCnt的字段 if (onlineCnt==null){ onlineCnt= 1; }else { onlineCnt = onlineCnt+1; } context.setAttribute("onlineCnt",onlineCnt);//每次添加这字段 } public void sessionDestroyed(HttpSessionEvent se) {//注销方法 ServletContext context = se.getSession().getServletContext(); Integer onlineCnt = (Integer) context.getAttribute("onlineCnt"); if (onlineCnt==null){ onlineCnt= 0; }else { onlineCnt = onlineCnt - 1; } context.setAttribute("onlineCnt",onlineCnt); }1
2
3
4
5
6
7
8
- 编写jsp与此类对应
- ```jsp
<body>
<h1>当前的在线人数有<span style="color: lightblue"><%=this.getServletConfig().getServletContext().getAttribute("onlineCnt")%></span>人</h1>
</body>
<%--通过EL表达式拿到关联类的字段-%>
12.JBDC
12.1配置信息
1 | String url = "jdbc:mysql://localhost:3306/test01?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"; |
12.2加载驱动
1 | Class.forName("com.mysql.cj.jdbc.Driver") ; |
12.3连接数据库
1 | Connection connection = DriverManager.getConnection(url, username, password); |
12.4向数据库发送statement请求,CRUD
1 | Statement statement = connection.createStatement(); |
前面这些步骤都是固定的,需要的时候改一改username,url,password
#### 12.5写sql
1 | String sql ="select *from person"; |
12.6执行sql
1 | ResultSet res = statement.executeQuery(sql); |
12.7 关闭连接
- 先开后关
1 | res.close(); |
记录一个小问题
- 关于idea的控制台里输出的内容的乱码问题(是指原来sout在控制台里的东西),需要在tomcat配置的时候的VM options里配置
1 | -Dfile.encoding=UTF-8 |
- 解决乱码
1 | .setContentType("text/html;charset = utf-8"); |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 磊磊の小窝!





