简介
本章不涉及安全部份,为学习javaweb安全的必备基础,为以后学习铺垫。
资源&书签索引
java代码审之路https://www.cnblogs.com/afanti/p/13156152.html
靶场https://github.com/JoyChou93/java-sec-code
java反射机制详解
网课笔记
课程:https://www.imooc.com/learn/199
(老师的声音有点像蕾丝
Class类
class类是java.lang中的类,java中的class类只能由JVM访问。
任何一个类都是Class类的实例对象,这个实例对象有三种表达方式
我们也可以通过类的类型来实例化这个类
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 30 31 32 33 34 35 36
| package com.day1;
public class ReflectDemo1 { public static void main(String[] args) throws InstantiationException, IllegalAccessException { Foo foo1 = new Foo(); Class c1 = Foo.class; Class c2 = foo1.getClass();
Class c3 = null; try { c3 = Class.forName("com.day1.Foo"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println(c3==c2);
Foo foo = (Foo) c3.newInstance(); foo.print();
} } class Foo{ void print(){ System.out.println("Foo print"); } }
|
Java动态加载类
Class.forName()表示了动态加载类,表示动态编译。
编译时加载类是静态加载类
运行时加载类是动态加载类
获取方法信息
基本的数据类型也存在对应的类类型
编写一个工具类进行练习,存在一个打印传入类信息的方法,使用反射实现
方法信息被封装在java.lang.reflect.Method中
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 30 31 32 33
| package com.day1;
import java.lang.reflect.Method;
public class ClassUtil { public static void printClassMessage(Object obj){ Class c = obj.getClass(); System.out.println("该类的名称是==>"+c.getName());
Method[] methods = c.getMethods(); for (int i = 0; i < methods.length; i++) { Class<?> returnType = methods[i].getReturnType(); System.out.print(returnType.getName()+" "); System.out.print(methods[i].getName()+"("); Class<?>[] parameterTypes = methods[i].getParameterTypes(); for (Class class1 : parameterTypes){ System.out.print(class1.getName()+","); } System.out.println(")"); } } }
|
获取其他的信息
我们可以通过类类型(Class Type)来获取方法信息,也就说明我们可以通过它获取别的信息
例如成员变量信息,它被封装在java.lang.reflect.Field中
构造函数信息,它被封装在java.lang.reflect.Constructor中
我们可以通过对象来获取到类的其他信息
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 30 31 32 33 34 35 36 37 38
|
public static void printFieldMessage(Object obj) { Class<?> c = obj.getClass(); Field[] fs = c.getDeclaredFields(); for (Field field : fs) { Class fieldType = field.getClass(); String typeName = fieldType.getName(); String fieldName = field.getName(); System.out.println("typename:" + typeName + " fieldName:" + fieldName); } }
public static void printConMessage(Object obj){ Class<?> c = obj.getClass(); Constructor[] constructors = c.getDeclaredConstructors(); for (Constructor constructor1: constructors ) { String constructor1Name = constructor1.getName(); System.out.print(constructor1Name+"("); Class[] parameterTypes = constructor1.getParameterTypes(); for (Class class1:parameterTypes ) { System.out.print(class1.getName()+","); } System.out.println(")"); } }
|
方法反射的基本操作
如何获取某个方法
方法的名称和方法的参数列表,才能唯一决定某个方法
如何方法反射的操作
method.invoke(对象,参数列表)
TestMehod类:
1 2 3 4 5 6 7 8 9
| class TestMehod { public void print(int a,int b){ System.out.println(a+b); }
public void print(String a,String b){ System.out.println(a.toUpperCase()+b); } }
|
获取一个方法,首先要获取类的信息
获取类的信息先要获取类的参数列表
1 2 3
| TestMehod test = new TestMehod(); Class aClass = test.getClass();
|
获取方法,要求方法名和参数列表
getMethod获取到public的方法,getDeclaredMethod获取到声明了的方法
1 2 3
| / aClass.getMethod("print", int.class, int.class)
Method m = aClass.getDeclaredMethod("print", int.class, int.class);
|
然后通过获取到的方法,来进行方法调用
也就是方法的反射操作,反过来通过操作test对象来调用方法
1 2 3
| Object o2 = m.invoke(test, 1, 2);
|
同样:
等价于test.print(“hello”,”WORLD”);
1 2 3 4
| Method m2 = aClass.getMethod("print", String.class, String.class);
Object o2 = m2.invoke(test, "hello", "WORLD");
|
如果想要获取的方法没有参数可以这样写
1 2
| Method m3 = aClass.getMethod("print",new Class[]{}); Method m3 = aClass.getMethod("print");
|
通过反射来了解泛型的本质
通过Class,Method来了解泛型的本质
之前我们使用集合:
1 2 3
| ArrayList list = new ArrayList(); ArrayList<String> list1 = new ArrayList<>();
|
其实,之前所说的类类型,也可以叫做字节码
因为反射的操作都是编译之后的操作
1 2 3
| Class c1 = list.getClass(); Class c2 = list1.getClass(); System.out.println(c1==c2);
|
所以java中,集合的泛型是防止错误输入的,只在编译阶段有效
编译之后泛型就无效了
我们可以通过方法的反射来操作,绕过泛型的限制
1 2 3 4
| Method add = c1.getMethod("add", Object.class); add.invoke(list1,100);
System.out.println(list1.toString());
|
反射的操作,一系列操作都是绕过编译,在运行时刻执行的。
什么是反射
(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息(此时已经编译后),从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
反射的原理
下图是类的正常加载过程、反射原理与class对象:
Class对象的由来是将**.class文件读入内存,并为之创建一个Class对象。**
反射的优缺点
1、优点:在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
2、缺点:
(1)反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。
反射的用途
1、反编译:.class–>.java
2、通过反射机制访问java对象的属性,方法,构造方法等
3、当我们在使用IDE,比如Ecplise时,当我们输入一个对象或者类,并想调用他的属性和方法是,一按点号,编译器就会自动列出他的属性或者方法,这里就是用到反射。
4、反射最重要的用途就是开发各种通用框架。比如很多框架(Spring)都是配置化的(比如通过XML文件配置Bean),为了保证框架的通用性,他们可能需要根据配置文件加载不同的类或者对象,调用不同的方法,这个时候就必须使用到反射了,运行时动态加载需要的加载的对象。
5、例如,在使用Strut2框架的开发过程中,我们一般会在struts.xml里去配置Action,比如
1 2 3 4
| <action name="login" class="org.ScZyhSoft.test.action.SimpleLoginAction" method="execute"> <result>/shop/shop-index.jsp</result> <result name="error">login.jsp</result> </action>
|
比如我们请求login.action时,那么StrutsPrepareAndExecuteFilter就会去解析struts.xml文件,从action中查找出name为login的Action,并根据class属性创建SimpleLoginAction实例,并用Invoke方法来调用execute方法,这个过程离不开反射。配置文件与Action建立了一种映射关系,当View层发出请求时,请求会被StrutsPrepareAndExecuteFilter拦截,然后StrutsPrepareAndExecuteFilter会去动态地创建Action实例。
比如,加载数据库驱动的,用到的也是反射。
1
| Class.forName("com.mysql.jdbc.Driver");
|
反射机制常用的类
Java.lang.Class;
Java.lang.reflect.Constructor;
Java.lang.reflect.Field;
Java.lang.reflect.Method;
Java.lang.reflect.Modifier;
Tomcat
tomcat目录结构:https://www.jianshu.com/p/81ec9c51435e
tomcat配置文件详解:https://www.cnblogs.com/54chensongxia/p/13255055.html
tomcat目录结构及配置文件:https://blog.51cto.com/botao/72331
Maven
在javaweb开发中,需要使用大量的jar包,这些jar包需要我们手动导入,一般在lib文件夹下,
Maven是一个架构管理工具
Maven的核心思想:约定大于配置
配置环境变量,换源
1 2 3 4 5 6
| <mirror> <id>nexus-aliyun</id> <mirrorOf>central</mirrorOf> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror>
|
建立一个本地仓库
1
| <localRepository>C:\JAVA\apache-maven-3.8.4\maven-repo</localRepository>
|
在idea中配置maven
idea项目创建成功之后,看一眼配置,确认maven配置在自己本地的目录下面
配置tomcat解释器
虚拟路径映射
pom.xml
maven之pom.xml配置文件详解https://www.jianshu.com/p/0e3a1f9c9ce7
远程仓库
https://mvnrepository.com/
Servlet
第一个Servlet
servlet是sun公司开发动态web的一门技术
- 编写一个类,实现servlet接口
- 把开发好的Java类部署到web服务器中
添加依赖
HelloServlet
创建一个普通的Maven项目,删掉里面的src目录,之后直接建立模块,这个空工程就是Maven主工程
关于Maven父子工程的理解
maven环境优化
1.修改web.xml为最新的
2.将maven结构完整
编写一个Servlet程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter(); writer.print("Hello Servlet");
}
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } }
|
编写Servlet的映射
我们写的是java程序,但是需要通过浏览器访问,而浏览器需要连接web服务器,所以我们要在web服务中注册我们写的Servlet
还要给他一个浏览器能够访问的路径
注册Servlet:
src/main/webapp/WEB-INF/web.xml
1 2 3 4 5 6 7 8 9 10
| <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.kuang.servlet.HelloServlet</servlet-class> </servlet>
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
|
配置Tomcat
发布路径
编译之后发布的网站目录
Servlet原理
Servlet体系结构
Servlet的框架是由两个Java包组成的:javax.servlet与javax.servlet.http。
在javax.servlet包中定义了所有的Servlet类都必须实现或者扩展的通用接口和类。
在javax.servlet.http包中定义了采用Http协议通信的HttpServlet类。
Servlet的框架的核心是javax.servlet.Servlet接口,所有的Servlet都必须实现这个接口。
1 2 3 4 5
| 1. init(ServletConfig)方法:负责初始化Servlet对象,在Servlet的生命周期中,该方法执行一次;该方法执行在单线程的环境下,因此开发者不用考虑线程安全的问题; 2. service(ServletRequest req,ServletResponse res)方法:负责响应客户的请求;为了提高效率,Servlet规范要求一个Servlet实例必须能够同时服务于多个客户端请求,即service()方法运行在多线程的环境下,Servlet开发者必须保证该方法的线程安全性; 3. destroy()方法:当Servlet对象退出生命周期时,负责释放占用的资源; 4. getServletInfo:就是字面意思,返回Servlet的描述; 5. getServletConfig:这个方法返回由Servlet容器传给init方法的ServletConfig。
|
ServletRequest & ServletResponse
对于每一个HTTP请求,servlet容器会创建一个封装了HTTP请求的ServletRequest实例传递给servlet的service方法,ServletResponse则表示一个Servlet响应,其隐藏了将响应发给浏览器的复杂性。通过ServletRequest的方法你可以获取一些请求相关的参数,而ServletResponse则可以将设置一些返回参数信息,并且设置返回内容。
Servlet工作原理
当Web服务器接收到一个HTTP请求时,它会先判断请求内容:
如果是静态网页数据,Web服务器将会自行处理,然后产生响应信息;
如果牵涉到动态数据,Web服务器会将请求转交给Servlet容器。此时Servlet容器会找到对应的处理该请求的Servlet实例来处理,结果会送回Web服务器,再由Web服务器传回用户端。
接着我们描述一下Tomcat与Servlet是如何工作的,首先看下面的时序图:
- Web Client 向Servlet容器(Tomcat)发出Http请求;
- Servlet容器接收Web Client的请求;
- Servlet容器创建一个HttpRequest对象,将Web Client请求的信息封装到这个对象中;
- Servlet容器创建一个HttpResponse对象;
- Servlet容器调用HttpServlet对象的service方法,把HttpRequest对象与HttpResponse对象作为参数传给 HttpServlet对象;
- HttpServlet调用HttpRequest对象的有关方法,获取Http请求信息;
- HttpServlet调用HttpResponse对象的有关方法,生成响应数据;
- Servlet容器把HttpServlet的响应结果传给Web Client;
Servlet生命周期
在Servlet接口中定义了5个方法,其中3个方法代表了Servlet的生命周期:
1 2 3
| 1. init(ServletConfig)方法:负责初始化Servlet对象,在Servlet的生命周期中,该方法执行一次;该方法执行在单线程的环境下,因此开发者不用考虑线程安全的问题; 2. service(ServletRequest req,ServletResponse res)方法:负责响应客户的请求;为了提高效率,Servlet规范要求一个Servlet实例必须能够同时服务于多个客户端请求,即service()方法运行在多线程的环境下,Servlet开发者必须保证该方法的线程安全性; 3. destroy()方法:当Servlet对象退出生命周期时,负责释放占用的资源;
|
servlet-mapping的配置与问题
https://blog.csdn.net/qfikh/article/details/52565976
Servlet的详细使用
ServletContext
https://blog.csdn.net/gavin_john/article/details/51399425
web容器在启动的时候,他会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用
- 共享数据
- 获取初始化参数
context.getInitParameter()
- 请求转发
context.getRequestDispatcher()
- 读取资源文件
编写一个ServletContext
需要一个放置数据的类,需要一个读取的类,然后配置web.xml
编写一个Servlet,获取到ServletContext类,往里面加入一个属性
1 2 3 4 5 6 7 8 9 10
| public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext();
String username = "admin"; context.setAttribute("username",username);
} }
|
写另一个类,在其中获取到和上面一样的ServletContext类,在里面取出属性并打印到页面中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class GetServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); String username = (String) context.getAttribute("username");
resp.getWriter().println("username:"+username);
}
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } }
|
写完之后注册路由
读取资源文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class PropertiesServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties(); prop.load(is); String user = prop.getProperty("username"); String pwd = prop.getProperty("password");
resp.getWriter().println("user:"+user+" pwd:"+pwd); }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } }
|
HttpServletResponse
web服务器接收到客户端的http请求,会针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse
- 如果要获取客户端请求过来的参数:找HttpServletRequest
- 如果要给客户端响应一些个信息,找HttpServletResponse
https://www.cnblogs.com/xdp-gacl/p/3798347.html
常见应用:
向浏览器输出消息
下载文件:
- 要获取下载文件的路径
- 下载的文件名字是什么
- 设置想办法让浏览器能支持我们下载的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutPutStream对象
- 将FileOutPutStream写入到缓冲区Buffer
- 将Buffer中的数据输出到客户端
下载文件
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 30 31 32 33 34 35 36 37 38 39 40 41 42
| package com.kuang.servlet;
import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileInputStream; import java.io.IOException;
public class FileServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String realPath = "C:\\Users\\Liyc\\IdeaProjects\\javaweb-1-study\\servlet-03\\target\\classes\\1.jpg"; System.out.println("Download path: "+realPath);
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
resp.setHeader("Content-disposition","attachment;filename="+fileName); FileInputStream in = new FileInputStream(realPath); int len = 0; byte[] buffer = new byte[1024]; ServletOutputStream out = resp.getOutputStream(); while((len=in.read(buffer))>0) { out.write(buffer,0,len); } in.close(); out.close(); }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } }
|
实现后端验证码
需要用到java的图片类,生成一个图片
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| package com.kuang.servlet;
import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random;
public class ImageServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setHeader("refresh","5");
BufferedImage bufferedImage = new BufferedImage(200,40,BufferedImage.TYPE_INT_RGB); Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics(); graphics.setColor(Color.MAGENTA); graphics.fillRect(0,0,200,40); graphics.setColor(Color.BLUE); graphics.setFont(new Font(null,Font.BOLD,20)); graphics.drawString(makeNum(),100,20);
resp.setContentType("image/jpeg"); resp.setDateHeader("expires",-1); resp.setHeader("Cache-Control","no-cache"); resp.setHeader("Pragma","no-cache");
ImageIO.write(bufferedImage,"jpg",resp.getOutputStream()); }
private String makeNum(){ Random random = new Random(); String num = random.nextInt(9999) + ""; StringBuffer sb = new StringBuffer(); for (int i = 0; i < 4-num.length(); i++) { sb.append("0"); } return sb.toString() + num;
} @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } }
|
实现重定向(*)
1
| resp.sendRedirect("/s3/image");
|
HttpServletRequest
处理客户端发来的http请求并处理
1.获取前端传递的参数
index.jsp
以post的方式提交表单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登录</title> </head> <body> <form action="${pageContext.request.contextPath}/login" method="POST"> <h1>Login</h1> <input type="text" name="username" placeholder="Username"> <input type="password" name="password" placeholder="password"> <input type="checkbox" name="hobbies" value="Video game"> <input type="checkbox" name="hobbies" value="Animation"> <input type="checkbox" name="hobbies" value="Football"> <input type="submit" name="" value="Login"> </form> </body>
</html>
|
写一个Servlet来获取参数和请求转发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); String username = req.getParameter("username"); String password = req.getParameter("password"); String[] hobbies = req.getParameterValues("hobbies"); System.out.println(username); System.out.println(password); System.out.println(Arrays.toString(hobbies));
req.getRequestDispatcher("/success.jsp").forward(req,resp); } }
|
2.请求转发
实现Cookie
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 30 31 32 33 34 35 36
| public class CookieDemo extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
Cookie[] cookies = req.getCookies();
if (cookies!=null){ out.write("你上一次访问的时间是:"); for (Cookie cookie:cookies ) { if(cookie.getName().equals("loginTime")){ String value = cookie.getValue(); long time = Long.parseLong(value); Date date = new Date(time); out.write(date.toLocaleString()); } } }else { out.write("这是第一次访问"); }
Cookie cookie = new Cookie("loginTime", System.currentTimeMillis()+""); resp.addCookie(cookie); }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } }
|
Session
在web.xml中可以配置session的一些配置
1 2 3 4
| <session-config> <session-timeout>15</session-timeout> </session-config>
|
实现session中读取数据功能
存数据
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 30 31
| public class SessionDemo extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=utf-8");
HttpSession session = req.getSession();
Person xianbei = new Person("xianbei", 20); session.setAttribute("name",xianbei);
String id = session.getId();
if(session.isNew()){ resp.getWriter().write("session创建成功,id:"+session); }else{ resp.getWriter().write("session已经存在"); } }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
|
取数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class SessionDemo02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=utf-8");
HttpSession session = req.getSession();
Object name = session.getAttribute("name"); resp.getWriter().write(name.toString()); }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
|
JSP
jsp原理
Java Server Pages
https://cloud.tencent.com/developer/article/1174274
JSP其实是对Servlet进行了包装而已。
jsp + java类(service、javabean)+ servlet,就会构成mvc的开发模式,mvc模式是目前软件公司中相当通用的开发模式。
浏览器向服务器发出什么请求,都是在访问Servlet
1.判断请求
2.内置一些对象
jsp基础语法和指令
https://www.cnblogs.com/qlqwjy/p/8943061.html
maven配置
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
| <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency>
<dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency>
<dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl-api</artifactId> <version>1.2</version> </dependency>
<dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency>
|
JSP表达式
将程序的结果输出到客户端
1 2 3 4 5 6 7 8 9
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head> <body> <%= new java.util.Date()%> </body> </html>
|
JSP脚本片段
1 2 3 4 5 6 7
| <% int sum = 0; for (int i = 0; i < 10; i++) { sum+=i; } out.print(sum); %>
|
JSP声明:会被编译到JSP生成的类中,其他的会被生成到_jspService方法中
JSP注释(在查看页面源码的时候不会看见)
语法 |
描述 |
<%– 注释 –%> |
JSP注释,注释内容不会被发送至浏览器甚至不会被编译 |
|
HTML注释,通过浏览器查看网页源代码时可以看见注释内容 |
<% |
代表静态 <%常量 |
%> |
代表静态 %> 常量 |
' |
在属性中使用的单引号 |
" |
在属性中使用的双引号 |
JSP指令
JSP指令用来设置与整个JSP页面相关的属性。
指令 |
描述 |
<%@ page … %> |
定义页面的依赖属性,比如脚本语言、error页面、缓存需求等等 |
<%@ include … %> |
包含其他文件 |
<%@ taglib … %> |
引入标签库的定义,可以是自定义标签 |
JSP标签(行为)
语法 |
描述 |
jsp:include |
用于在当前页面中包含静态或动态资源 |
jsp:useBean |
寻找和初始化一个JavaBean组件 |
jsp:setProperty |
设置 JavaBean组件的值 |
jsp:getProperty |
将 JavaBean组件的值插入到 output中 |
jsp:forward |
从一个JSP文件向另一个文件传递一个包含用户请求的request对象 |
jsp:plugin |
用于在生成的HTML页面中包含Applet和JavaBean对象 |
jsp:element |
动态创建一个XML元素 |
jsp:attribute |
定义动态创建的XML元素的属性 |
jsp:body |
定义动态创建的XML元素的主体 |
jsp:text |
用于封装模板数据 |
1
| <jsp:include page="date.jsp" flush="true" />
|
JSP九大内置对象
对象 |
描述 |
request |
HttpServletRequest类的实例 |
response |
HttpServletResponse类的实例 |
out |
PrintWriter类的实例,用于把结果输出至网页上 |
session |
HttpSession类的实例 |
application |
ServletContext类的实例,与应用上下文有关 |
config |
ServletConfig类的实例 |
pageContext |
PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问 |
page |
类似于Java类中的this关键字 |
Exception |
Exception类的对象,代表发生错误的JSP页面中对应的异常对象 |
JSP四大作用域
page、request、session、application
JSTL核心标签
https://www.runoob.com/jsp/jsp-jstl.html
JavaBean
实体类
有特定的写法
- 必须有个无参构造
- 属性必须私有化
- 必须有对应的get和set
一般用来和数据库的字段做映射
ORM:对象关系映射
MVC
https://openhome.cc/Gossip/Spring/MVC.html
过滤器Filter
用来过滤网站的数据
过滤器中的所有代码,在过滤特定请求的时候都会执行
必须要让过滤器继续通行filterChain.doFilter(servletRequest, servletResponse);
实现一个编码转换过滤器
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
| import javax.servlet.*; import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
@Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("初始化——————"); }
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding("UTF-8"); servletResponse.setCharacterEncoding("UTF-8"); servletResponse.setContentType("text/html;charset=UTF-8");
System.out.println("执行前"); filterChain.doFilter(servletRequest, servletResponse); System.out.println("执行后"); }
@Override public void destroy() { System.out.println("销毁——————"); } }
|
web.xml中注册过滤器
1 2 3 4 5 6 7 8
| <filter> <filter-name>character</filter-name> <filter-class>com.kuang.filter.CharacterEncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>character</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|
监听器
实现一个监听器的接口,监听器有很多种,选择我们需要的接口即可