文章目錄
一、基礎
參考:https://mp.weixin.qq.com/s/6Mln9NOR2vg0p7u4Sc7kxQ
1.1 含義
含義:相當於Servlet的框架,Servlet的升級版。web請求與處理方法的映射。
作用:
1、框架幫我們封裝了很多常用的功能。
——把Web帶過來的參數自動封裝到JavaBean中。
2、更加靈活。
——不用把路徑等信息寫死在程序上,使用配置文件來管理路徑。若目錄發生變化,不用一個一個去修改每個程序的路徑。
3、更加簡潔。
——每個Servlet中都有doGet和doPost這樣的方法,沒必要的。抽取出來,通過配置文件來把這兩個方法替換掉,程序就會更加簡潔、優雅。
1.2 用戶登陸註冊
1.2.1 DAO層和Service層
UserDao.java
public class UserDao {
public User login(User user) {
if ("admin".equals(user.getUsername()) && "123456".equals(user.getPsd())){
System.out.println("登陸成功!");
return user;
} else {
System.out.println("登陸失敗!");
return null;
}
}
public void register(User user) {
System.out.println("註冊成功!" + user.getUsername());
}
}
UserService.java
public class UserService {
private UserDao userDao = new UserDao();
public User longin(User user) {
return userDao.login(user);
}
public void register(User user) {
userDao.register(user);
}
}
1.2.2 JSP層
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/servlet/LoginServlet" method="post">
用戶名:<input type="text " name="username">
密碼:<input type="password " name="psd">
<input type="submit" value="登陸">
</form>
</body>
</html>
register.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/servlet/RegisterServlet" method="post">
用戶名:<input type="text " name="username">
密碼:<input type="password " name="psd">
<input type="submit" value="註冊">
</form>
</body>
</html>
1.2.3 傳統方法——Servlet層
說明
前端控制器:Servlet。
1、直接使web請求的url與Servlet的方法進行映射
2、然後進行頁面的內部轉發或請求重定向,到相應的頁面。
LoginServlet.java
// 此處使用了註解,也可以使用web.xml設置web請求與Servlet的映射。
@javax.servlet.annotation.WebServlet(name = "LoginServlet",urlPatterns = "/servlet/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 第一步:得到用戶帶過來的數據,並封裝到Bean對象中
String username = request.getParameter("username");
String psd = request.getParameter("psd");
User user = new User();
user.setPsd(psd);
user.setUsername(username);
try {
// 第二步:調用Service層方法
UserService userService = new UserService();
userService.longin(user);
// 第三步:跳轉到相應頁面
request.getRequestDispatcher("/index.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
//登陸失敗,跳轉到相關的提示頁面
request.setAttribute("message","登陸失敗了!!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
RegisterServlet.java
@javax.servlet.annotation.WebServlet(name = "RegisterServlet",urlPatterns = "/servlet/RegisterServlet")
public class RegisterServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String psd = request.getParameter("psd");
User user = new User();
user.setPsd(psd);
user.setUsername(username);
try {
UserService userService = new UserService();
userService.register(user);
request.getRequestDispatcher("/login.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("message","註冊失敗了!!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
web.xml
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/LoginServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/servlet/RegisterServlet</url-pattern>
</servlet-mapping>
缺點:
1、一個功能對應一個Servlet,太麻煩了。
2、跳轉頁面的路徑是寫死的。在註冊成功了以後,可以跳轉到首頁上,也可以跳轉到登陸的界面上。如果我要選擇其中的一個,就必須修改源代碼。
1.2.4 新型方法——Servlet層
使用Struts2框架進行管理,提高開發效率。
Action作用:代替Servlet的作用,同時將url與方法、頁面映射單獨寫在一個xml文件中,目的簡潔明瞭,便於維護。
Struts2框架預先實現了一些功能:
——請求數據自動封裝
——文件上傳的功能
——對國際化功能的簡化
——數據效驗功能等
二、Struts2開發步驟
2.1 配置環境
2.1.1 引入jar文件
常用jar包 | 作用 |
---|---|
commons-fileupload-1.2.2.jar | 文件上傳相關包 |
commons-io-2.0.1.jar | 文件上傳相關包 |
struts2-core-2.3.4.1.jar | struts2核心功能包 |
xwork-core-2.3.4.1.jar | Xwork核心包 |
ognl-3.0.5.jar | Ognl表達式功能支持表 |
commons-lang3-3.1.jar | struts對java.lang包的擴展 |
freemarker-2.3.19.jar | struts的標籤模板庫jar文件 |
javassist-3.11.0.GA.jar | struts對字節碼的處理相關jar |
2.1.2 配置web.xml
配置Struts2核心過濾器.
注意:若web.xml配置了多個fileter,那麼struts的filter需要在最後面!
<!-- 引入struts核心過濾器 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<!-- struts過濾器映射。過濾的URL類型。 -->
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.2 開發Action
Action類也叫動作類,處理請求的類。
1、extends ActionSupport類。
2、重寫execute()方法,當然也可以不重寫。
public class HelloAction extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("helloworld");
return "success";
}
}
2.3 配置struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="hello" extends="struts-default">
<action name="hello" class="action.HelloAction" method="execute">
<result name="success">/index.jsp</result>
</action>
</package>
</struts>
三、Struts2執行流程
3.1 服務器啓動
加載順序:
1、加載web.xml文件。
2、找到我們配置的filter中的StrutsPrepareAndExecuteFilter
3、StrutsPrepareAndExecuteFilter在裏邊執行init()方法。
4、一直到Dispatcher dispatcher = init.initDispatcher(config);,初始化dispatcher
5、在初始化dispatcher的時候加載struts-default.xml和我們配置的struts.xml
struts-default.xml:
1、< bean>標籤: 指定了struts在運行的時候需要創建的對象類型。
——在運行struts的時候,可能需要創建一些對象,那麼就通過Bean來指定。
2、< interceptor>標籤: 是struts定義的攔截器,一共有32個。
——Struts爲我們實現了一些功能,就是通過攔截器來實現的。
3、< result-type>標籤: 跳轉結果的類型。
——Action業務方法中的返回值。redirect【重定向】、dispatcher【轉發】、redirectAction【重定向到Action資源】、stream【文件下載的時候用】。
4、< interceptor-stack>標籤:攔截器的棧。
——攔截器有32個,我們可能會使用很多的攔截器,不可能一個一個來調用,於是提供了攔截器棧…其實可以簡單看成**文件夾和文件之間的關係 **。
5、< default-interceptor-ref>標籤:默認執行的攔截器棧,默認的攔截器棧有18個攔截器。
6、< default-class-ref>標籤:默認的執行Action類。
攔截器和過濾器
1、攔截器和過濾器都是攔截資源的。
2、攔截器只攔截Action請求,是struts的概念。
3、過濾器攔截web的所有資源,是Servlet的概念。
小總結
1、服務器啓動的時候,其實就是加載了web.xml文件,然後調用init()方法去加載struts.xml和struts-default.xml之類的文件……
2、此時的攔截器是還沒有被調用的。
3.2 訪問階段
在服務器啓動的階段,僅僅是加載了各種的xml文件。
訪問Action時的執行流程:
1、它會創建我們在struts.xml中配置的Action對象。
2、它會按照默認的順序執行18個攔截器【也就是調用默認攔截器棧】。
3、它會執行Action的業務方法【也就是execute(),我們在struts.xml文件中配置了什麼,就執行什麼業務方法】。
注意:每訪問Action一次,它就會創建一個對象。它並不是和Servlet一樣只有一個對象。因此它是線程安全的。
四、struts.xml
<struts>
<package name="hello" extends="struts-default">
<action name="hello" class="action.HelloAction" method="execute">
<result name="success">/index.jsp</result>
</action>
</package>
</struts>
4.1 package標籤
含義:package其實就是包。包就是用來管理Action。
注意:通常,一個業務模版對應一個package。
屬性:
name:包的名字。包的名稱是不能重複的。
extends:當前包繼承着哪個包。在struts中,包一定要繼承着struts-default。
abstract:當前包被其他的包繼承…並且,在package下不能有action,否則會出錯!
namespace:作爲路徑的一部分的,默認是"/"。
4.2 actoin標籤
含義:置請求路徑與Action類的映射關係
屬性:
name:請求路徑的名字
class:處理action類的全名。
method:調用的方法名稱
4.3 result標籤
含義:是Action中業務方法返回的值
屬性:
name:action處理返回的值。
type:跳轉的類型。redirect【重定向】、dispatcher【轉發】、redirectAction【重定向到Action資源】、stream【文件下載的時候用】。
文本值:跳轉的路徑。
4.4 子xml文件
1、一個package應該對應一個業務模塊,目的就是把職能細分出來
2、struts爲了讓我們更好地管理xml文件,它還可以這樣做:在不同的模塊中用不同的xml文件進行描述…
3、在struts.xml文件中將其引入即可。
<!--struts在運行的時候總會加載這個文件-->
<!--總配置文件總引入其他的文件-->
<struts>
<include file="privilegeaction/privilege.xml"/>
<include file="useraction/hello.xml"/>
</struts>