目录
- MVC
- 网页获取动态资源逻辑
- 定义
- 举个
- 优缺点
- 参考博客
- 三层架构
- 举个
- 优缺点
- MVC和三层架构的区别
- 参考博客
- Servlet
- 工作模式
- Servlet的开发流程
- web.xml配置servlet
- @注解配置servlet
- 映射路径通配符
- Servlet的生命周期
- ServletConfig接口
- HttpServlet抽象类
- 为什么?
- GenericServlet抽象类
- 回到HttpServlet
- service(HttpServletRequest, HttpServletResponse)自定义方法,根据请求的方式去调用不同的方法
- 为什么定义成抽象类?
- Servlet中四个重要的对象
- 转发和重定向
- 转发
- 重定向
- 转发和重定向的区别
- 一个Servlet小demo
- 小结
- 参考博客
MVC
MVC(Model View Controller)是软件工程中的一种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。以一种业务逻辑、界面显示、数据分离的方式组织代码,将业务逻辑聚集到一个部件里面(模型),在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
网页获取动态资源逻辑
- 网页界面
- 请求转发
- 接收请求
- 处理请求
- 返回数据
定义
- M:Model,模型。
- 完成具体的业务操作,如:查询数据库,封装对象
- V:view视图。JSP、HTML等来进行数据展示
- C:Controller控制器。 Servlet
- 获取View的请求
- 调用模型将数据交给视图进行展示
举个
控制器
Controller
的作用就是将Model
与View
一一对应起来
优缺点
【优点】
- 耦合性低,方便维护,可以利于分工协作
- 重用性高
【缺点】
- 使得项目架构变得复杂,对开发人员要求高
参考博客
MVC与三层架构理解
三层架构
通常意义上的三层架构就是将整个业务应用划分为:界面层[表示层] UI(User Interface layer)、业务逻辑层BLL(Business Logic Layer)、数据访问层DAL(Data access layer)。
区分层次的目的是为了“高内聚低耦合” 的思想。
举个
任何一层发生变化都不会影响到另外一层!!!
优缺点
【优点】
- 开发人员可以只关注整个结构中的其中某一层;
- 可维护性高,可扩展性高
- 可以降低层与层之间的依赖;
- 有利于标准化;
- 利于各层逻辑的复用
【缺点】
- 降低了系统的性能。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成
- 有时会导致级联的修改,这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码
- 增加了开发成本
MVC和三层架构的区别
参考博客
MVC与三层架构理解
Servlet
是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。
工作模式
- 客户端发送请求至服务器
- 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
- 服务器将响应返回客户端
在mvc架构中,servlet在其中承担的作用是controller,控制器。
控制器作用:
- 获取View的请求
- 调用模型(M)将数据交给视图(V)进行展示
web应用是基于http协议的,http协议有请求报文(request)和响应报文(request),请求报文就是浏览器向服务器发送的数据形成的数据对象,同理,响应报文就是服务器向浏览器发送的数据形成的信息,而http协议有两个重要的方法,一个是POST,一个是GET,这两个方法就是向浏览器发送请求的方法。
servlet能够读取请求报文的内容,并对报文进行处理。
Servlet的开发流程
狭义上讲,servlet是java语言实现的一个类,所以我们就要根据这个类进行相应的扩展开发。
具体流程如下:
- 编写一个java类,继承HttpServlet类(需要导入
servlet-api.jar
) - 重写HttpServlet类的doGet方法和doPost方法
- 配置web.xml文件,或者使用注解对servlet进行配置
web.xml配置servlet
配置格式示例
<webapp> <servlet> <servlet-name>MyServlet</servlet-name> <servlet-class>cn.roobtyan.servlet.FirstServlet</servlet-class> <init-param> <param-name>first</param-name> <param-value>第一个初始化参数</param-value> </init-param> <init-param> <param-name>second</param-name> <param-value>第二个初始化参数</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>MyServlet</servlet-name> <url-pattern>/first</url-pattern> </servlet-mapping></webapp>
访问/first的时候,服务器会把请求交给MyServlet进行处理。
标记容器何时加载servlet(实例化并调用init()方法)
为负值或者没有配置 ,则容器会当Servlet被请求时加载
为正整数或者0,则容器在应用启动时就加载并初始化
值越小,servlet的优先级越高,就越先被加载。值相同时,容器就会自己选择顺序来加载。
@注解配置servlet
@WebServlet(name = "LoginServlet",urlPatterns = {"/login"})public class LoginServlet extends HttpServlet {}
映射路径通配符
/*#任意路径都映射到这个servlet/bluemson/*#/bluemsun下的任意路径映射到该servlet
url要么以/开头,要么以*开头,其他的都是非法的
Servlet的生命周期
一般来讲,servlet只会初始化一次,也就是整个过程中只存在一个servlet对象,即便是有多次访问,依然只有一个对象,这个对象是可以复用的。
所以servlet是单实例多线程的。
Servlet接口
public interface Servlet { void init(ServletConfig var1) throws ServletException; //获得ServletConfig ServletConfig getServletConfig(); void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; String getServletInfo(); void destroy();}
其中init(),service(),destroy()比较关键,体现了Servlet的生命周期。
init方法只会调用一次,只是在创建servlet实例的时候才会创建
service方法,是进行数据处理的,只要接受了一次请求,就会被调用一次
destroy方法,销毁servlet对象的时候调用。停止服务器或者重新部署web应用时销毁servlet对象,同样也是调用一次
ServletConfig接口
public interface ServletConfig { //返回当前servlet的名字 String getServletName();//返回ServletContext(web应用的上下文) //每个web应用对应一个ServletContext,定义了servlet用来与servlet容器通信的多种方法 ServletContext getServletContext();//可以根据名字来获取servlet的初始化参数 String getInitParameter(String var1);//获取出初始化参数的参数名 Enumeration<String> getInitParameterNames();}
HttpServlet抽象类
虽然是抽象类但是没有抽象方法!
为什么?
每次要新建一个servlet都要实现Servlet接口,重写这好几个方法太麻烦啦!于是GenericServlet抽象类出现了。
GenericServlet抽象类
该类实现了Servlet, ServletConfig两个接口并重写了方法。
//只有一个抽象方法在继承GenericServlet时要实现public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
注意这里有两个重载的init()方法
- init(ServletConfig)是 GenericServlet 抽象类实现 servlet接口要实现的init方法,实现了原来Servlet的功能
- init()是GenericServlet 抽象了自己新添加的init方法,目的是让继承该抽象类的servlet被加载并初始化时可以自己做些自定义的初始化。
这时,如果我们继承GenericServlet 抽象类再写servlet已经简单多了。而继承了它的HttpServlet更加简单。
回到HttpServlet
该抽象类继承了GenericServlet 抽象类,并且重写了GenericServlet 中唯一的抽象方法service(ServletRequest,ServletRespone)方法
其中重点看两个重载的service方法
service(ServletRequest , ServletResponse)
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { //下转型为HttpServletRequest(ServletRequest子接口) HttpServletRequest request; //下转型为HttpServletRespone(ServletRespone子接口) HttpServletResponse response; try { request = (HttpServletRequest)req; response = (HttpServletResponse)res; } catch (ClassCastException var6) { throw new ServletException(lStrings.getString("http.non_http")); }//调用自定义的service方法 this.service(request, response); }
由于我们的请求都是http请求,所以把ServletRequest请求下转型为HttpServletRequest,ServletRespone请求下转型为HttpServletRespone,以获取更多关于请求的信息(如请求方式等),并调用自定义的service方法
service(HttpServletRequest, HttpServletResponse)自定义方法,根据请求的方式去调用不同的方法
当我们新建servlet的时候只需要继承HttpServlet,然后根据请求方式重写对应的doXXX()方法就行了
为什么定义成抽象类?
防止直接创建对象!单纯的HttpServlet对象时不能处理任何业务逻辑的,里边方法没有功能,需要继承它我们重写它的方法!
Servlet中四个重要的对象
HttpServletRequest 请求对象:获取请求信息HttpServletResponse 响应对象: 设置响应对象ServletConfig对象 servlet配置对象ServletContext对象 servlet的上下文对象
对应关系:Servlet与JSP九大内置对象的对应关系
这些上节课学姐的博客里也写的很详细了
蓝旭第四次培训——JSP
转发和重定向
转发
request.getRequestDispatcher("loginfal.jsp").forward(req,resp);
重定向
与转发功能相似的是重定向,重定向的使用是这样的:
response.sendRedirect("loginfal.jsp");
这样也会访问到loginfal.jsp这个页面。
转发和重定向的区别
虽然二者最终实现的功能是相同的.但是还是有很大不同的.不同之处如下:
- 地址栏变化
转发不会改变地址栏中的URL,而重定向则会改变 - 跳转范围
转发只能访问到当前web应用中的内容,而重定向则可以访问到任意web应用中的内容 - request对象作用范围
转发后,在转发后的页面中仍然可以使用原来的request对象,而重定向,原来的request对象则失去作用.
所以,如果想要在多个页面使用相同的request对象,那么只能使用转发,而不能使用重定向。
一个Servlet小demo
register.jsp
<html><head> <title>注册界面</title></head><body><form action="/register" method="get"> 账号:<input type="text" name="name"> <br> 密码:<input type="password" name="password"> <br> <input type="submit" value="注册"></form></body></html>
Register.java
import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;public class Register extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("name"); String password = req.getParameter("password"); HttpSession session = req.getSession(); User user = new User(); user.setName(name); user.setPassword(password); session.setAttribute("user",user);// req.getRequestDispatcher("registersuc.jsp").forward(req,resp); //设置响应的编码格式为UTF-8编码,否则发生中文乱码现象 resp.setContentType("text/html;charset=UTF-8"); //1.获得请求方式 String method = req.getMethod(); //2.获得请求的资源相关的内容 //获得请求URI String requestURI = req.getRequestURI(); //获得应用路径(应用名称) String webName = req.getContextPath(); //获得查询字符串 String querryString = req.getQueryString(); resp.getWriter().write("下面是获得的字符串
"); resp.getWriter().write("method(HTTP方法):"
); resp.getWriter().write(""
+method+"
"); resp.getWriter().write("requestURi(请求URI):
"); resp.getWriter().write(""
+ requestURI + "
"); resp.getWriter().write("webname(应用名称):
"); resp.getWriter().write(""
+ webName + "
"); resp.getWriter().write("querrystring(查询字符串):
"); resp.getWriter().write(""
+ querryString + "");// resp.sendRedirect("registersuc.jsp"); }}
web.xml
<servlet> <servlet-name>regiter</servlet-name> <servlet-class>Register</servlet-class> </servlet> <servlet-mapping> <servlet-name>regiter</servlet-name> <url-pattern>/register</url-pattern> </servlet-mapping>
jsp界面:
注册后显示的结果:
小结
参考博客
Servlet详细教程
JavaWeb——Servlet(全网最详细教程包括Servlet源码分析)
servlet入门&MVC
理解HttpServlet抽象类没有抽象方法(从Servlet–GenericServlet–HttpServlet)
servlet官方文档