Servlet详解,从无到有
什么是Servlet
Servlet是SUN公司提供的一门用于开发动态的web资源的技术,可以实现和客户端的交互,接收客户端的请求和客户端返回响应 Servlet是一个接口,用户如果想开发一个动态web资源需要: 1、编写一个java类,实现Servlet接口 2、把开发好的java类部署到web服务器中
Servlet的实现类
Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet、HttpServlet。
HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。
HttpServlet在实现Servlet接口时,重写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要重写doGet或doPost方法,而不要去重写service方法。
主要学习HttpServlet!
Servlet的注册
两种注册方法: 1、使用web.xml配置文件通过映射注册 2、使用@WebServlet()注解通过映射注册
使用web.xml配置文件通过映射注册
<servlet> //通过路径查找Servlet类 <servlet-name>Servlet01</servlet-name>//填写Servlet类名 <servlet-class>com.wangnian.servlet.Servlet01</servlet-class>//填写Servlet类在src目录下的路径 </servlet> //通过映射查找Servlet的类名,找到类名后查询上面<servlet>中对应的类的路径进行使用Servlet <servlet-mapping> <servlet-name>Servlet01</servlet-name>//Servlet类名 <url-pattern>/Servlet01</url-pattern>//前端连接地址的代号(自定义) </servlet-mapping>
使用@WebServlet()注解通过映射注册
@WebServlet("/Servlet01") //标记Servlet类 里面的value值自定义跟前端相同(servlet上别忘记了/)
其原理跟web.xml相同,更加简洁方便
注册时常用的参数
init方法为HttpServlet的方法,其功能就是对servlet对象进行初始化,提供config配置中的参数可以取出来方便使用
public void init(ServletConfig config) throws ServletException { System.out.println(config.getInitParameter("妄念")+config.getInitParameter("小明")); }
init中的参数为name的值跟value的值还有default(可忽略),也就是键值对 key=value
init在使用web.xml配置文件进行注册时的使用
<servlet> <servlet-name>Servlet01</servlet-name> <servlet-class>com.wangnian.servlet.Servlet01</servlet-class> //配置init的config的参数 <init-param> //这里只有一个也可以写多个键值对.... <param-name>name</param-name>//key <param-value>妄念</param-value>//value </init-param> </servlet>
init在@WebServlet注解中的使用
@WebServlet(value = "/Servlet02", //initParams是给出的一个数组可以进行一个或多个键值对的放置 name=value initParams = {@WebInitParam(name = "妄念",value = "123456"),@WebInitParam(name = "小明",value = "123456")} )
转发与重定向
转发:由服务器端进行的页面跳转(一次请求)
效果:http://localhost:8080/day11_war_exploded/Servlet03
重定向:由浏览器端进行的页面跳转(两次请求)
效果:http://localhost:8080/day11_war_exploded/login.html
转发语法:
// protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//由请求调用方法进行转发 request.getRequestDispatcher("login.html").forward(request,response); }
重定向语法:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//由响应调用方法 response.sendRedirect("login.html"); }
转发与重定向的区别:
区别 | 转发forward() | 重定向sendRedirect() |
---|---|---|
根目录 | 包含项目访问地址 | 没有项目访问地址 |
地址栏 | 不会发生变化 | 会发生变化 |
哪里跳转 | 服务器端进行的跳转 | 浏览器端进行的跳转 |
请求域中数据 | 不会丢失 | 会丢失 |
Servlet中文乱码问题
出现原因
前端后端编码不一致
浏览器默认使用UTF-8码表进行编码 ,Servlet使用ISO-8859-1码表进行编码
传输和接收方编码不一致导致乱码的产生
Request乱码
Request请求分为post和get,分别有不同的解决方案
Request乱码 - POST请求
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //给请求中的参数设置编码格式 request.setCharacterEncoding("UTF-8"); String parameter1 = request.getParameter("parameter1"); String parameter2 = request.getParameter("parameter2"); System.out.println(parameter1); System.out.println(parameter2); }
作用:设置从 request 中取得的值,用来指定对浏览器发送来的数据进行重新编码时,使用的编码。
使用注意事项:
在执行 setCharacterEncoding()之前,不能执行任何 getParameter()操作
通过 setCharacterEncoding 设置的编码方式只对 POST 方式提交的表单有效,对 GET 方式无效
Request乱码 - GET请求(Tomcat7.X版本)
解决方案1
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String parameter1 = request.getParameter("parameter1"); parameter1 = new String(parameter1.getBytes("ISO-8859-1"),"UTF-8"); String parameter2 = request.getParameter("parameter2"); parameter2 = new String(parameter2.getBytes("ISO-8859-1"),"UTF-8"); System.out.println(parameter1); System.out.println(parameter2); }
解决方案2
在Tomcat根目录/conf/server.xml中设置编码格式
<Connector URIEncoding="UTF-8" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
那么在启动服务器的时候就会读取到URIEncoding的属性配置,然后再调用自己的一个setURIEncoding方法完成设置,形参的值为我们设置的UTF-8
protected String URIEncoding = null; public void setURIEncoding(String URIEncoding) { this.URIEncoding = URIEncoding; setProperty("URIEncoding", URIEncoding); }
Request乱码 - GET请求(Tomcat8.X版本)
Tomcat8.x的服务器在接收GET请求时,即使参数中有中文,也不会出现乱码,作者在底层设计上的一些改动
Tomcat的连接器组件(Connector) ,Connector是Tomcat中的一个重要的组件,它负责监听Tomcat收到的请求信息,并将这些请求信息传递给Servlet规范中所定义的Request,然后将转换后的请求交给Engine组件
去处理,最后将Engine返回的Response返回给客户端 。源码中我们可以看到, URIEncoding的默认值为UTF-8,所以在Tomcat8.x中,即使GET请求包含了中文的数据,也不会出现乱码了
public class Connector extends LifecycleMBeanBase { private Charset uriCharset = StandardCharsets.UTF_8; //查询Tomcat根目录/conf/catalina.properties配置文件中的属性 public static final boolean RECYCLE_FACADES = Boolean.parseBoolean(System.getProperty("org.apache.catalina.connector.RECYCLE_FACADES", "false")); public Connector() { this(null); } public Connector(String protocol) { setProtocol(protocol); ProtocolHandler p = null; try { Class<?> clazz = Class.forName(protocolHandlerClassName); p = (ProtocolHandler) clazz.getConstructor().newInstance(); } catch (Exception e) { log.error(sm.getString( "coyoteConnector.protocolHandlerInstantiationFailed"), e); } finally { this.protocolHandler = p; } if (Globals.STRICT_SERVLET_COMPLIANCE) { uriCharset = StandardCharsets.ISO_8859_1; } else { uriCharset = StandardCharsets.UTF_8; } } }
Response乱码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置响应内容的编码格式 response.setContentType("text/html;charset=UTF-8"); response.getWriter().println("妄念"); }
跳转到中文页面路径乱码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.sendRedirect(URLEncoder.encode("详情页面.html", "UTF-8")); }