剛開始學習SSM框架,看着各式各樣的書,聽着大佬們錄的視頻,貌似覺得很簡單。但是親自實踐之后,就不會這么覺得了。
從github上拉了很多個項目下來,一個個花里胡哨,SSM框架結構命名各式各樣,一個jsp網頁或者java類就有成百上千行代碼,而我什么都看不懂。
其實那個時候我只想搞懂SSM環境配置的邏輯,以及前端網頁如何讀取數據庫中的數據(即前端網頁顯示數據庫數據),因為jsp網頁一旦能成功顯示數據庫中的數據,其他功能就可以以此類推,都是復制粘貼的事情了。
看不懂,沒人教,然后面向搜索引擎的編程,最后寫總結,已經是我長期以來的常態了。接着我就像做英語閱讀那樣,一行一行代碼的去查,最后把意思串起來,得到了我的理解。當然我的理解不一定准確,歡迎大佬指正。
總的思路:
前端網頁顯示數據庫數據大概分為以下八個步驟:
- 在web.xml中,使用<welcome-file-list>標簽,設置默認打開的網頁 /WEB-INF/views/login/test.jsp 。
- 在該前端網頁 test.jsp 中增加一個按鈕,按鈕指向"<%=basePath%>/summary/test1.do"(<%=basePath%>后面再說)。
- 該地址被 web.xml 中的DispatcherServlet(攔截器)所攔截,只剩下 /summary/test1 。
- web.xml 將 /summary/test1 傳送到 springmvc.xml ,接着springmvc.xml去掃描其管轄的包下有沒有對應的controller類。
- 在controller類(后端Java類)中找到@RequestMapping(value = "/summary/test1")的方法,執行這個方法。
- 在方法中,使用model.addAttribute(),像前端頁面傳送從數據庫讀取的數據,並且返回一個字符串"login/test"。
- 返回的字符串"login/test"在springmvc.xml的配置視圖解析器(ViewResolver)中,加上前綴"/WEB-INF/views/",加上后綴".jsp",即組成了一個完整的網頁地址,瀏覽器訪問的就是這個地址,即"/WEB-INF/views/login/test.jsp"。
- 前端網頁 test.jsp通過 ${msg} 來獲取后端發來的數據。
完整代碼放在最后面,先大概講一下每一步的邏輯思路
第一步
<welcome-file-list>
<welcome-file>/WEB-INF/views/login/test.jsp</welcome-file>
</welcome-file-list>
<welcome-file-list>標簽字面上看起來是歡迎文件列表的意思,實際上我猜是默認加載項目的網頁的意思。配置好這個,使用Tomcat運行,就會首先加載這個界面。
第二步
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path;
%>
<html>
<head>
<title></title>
</head>
<body>
<a href="<%=basePath%>/summary/test1.do">
<button>按鈕</button>
</a>
<h2>${msg}</h2>
</body>
</html>
request.getSchema()可以返回當前頁面使用的協議: http
request.getServerName()可以返回當前頁面所在的服務器的名字: localhost
request.getServerPort()可以返回當前頁面所在的服務器使用的端口: 8080;
request.getContextPath()可以返回當前頁面所在的應用的名字.如 /views/login/
總之就是要獲取到該項目的網絡路徑。
接着,我們使用 href="<%=basePath%>/summary/test1.do" 指向這個地址。
第三步
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
DispatcherServlet就是傳說中的攔截器,他能把第二步傳來的 /summary/test1.do ,攔截下來,去掉后綴 .do,並且把他發送到配置文件spring.mvc。
第四步
<context:component-scan base-package="ypc.zwz.controller"/>
springmvc.xml 收到數據之后,掃描這個包下所有的類,尋找有沒有和 /summary/test1 對應的方法。
第五、六步
package ypc.zwz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import ypc.zwz.service.ArticleService;
@Controller
@RequestMapping(value = "/summary")
public class ArticleController {
@Autowired
private ArticleService articleService;
@RequestMapping(value = "/test1")
public String te(@RequestParam(value = "pageCode", defaultValue = "1", required = false) int pageCode, @RequestParam(value = "pageSize", defaultValue = "3", required = false) int pageSize, HttpServletRequest request, Model model) {
Summary summary = articleService.findById(23);
String str = summary.getR_content();
model.addAttribute("msg",str);
return "login/test";
}
}
在ypc.zwz.controller包的ArticleController類中,找到與之對應的方法te();因為這個類@RequestMapping(value = "/summary"),類下的te方法@RequestMapping(value = "/test1"),組合起來就是 /summary/test1。所以執行這個方法。
先通過articleService.findById(23);即從Serive層讀取數據庫的信息(后面會給完整代碼),再獲取Summary類中的contnt屬性,通過model.addAttribute("msg",str);方法發送至前端頁面,前端頁面可以通過"msg"這個鍵來獲取到str這個值,最后向spring.mvc返回"login/test"這個字符串。
第七步
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
springmvc.xml 接收到返回來的"login/test"字符串,利用試圖解析器(ViewResolver)加上前綴后綴,組成完整的地址"/WEB-INF/views/login/test.jsp",返回到web.xml,瀏覽器正常讀取打開,就正常打開。
第八步
代碼見第二步,在第六步中已經說明,使用msg使用這個鍵來獲取到str這個值,所以使用 ${msg} ,就獲取到了后端傳過來的str的值。
關於為什么要把原本的網址搞得這么花里胡哨,可能是為了保密吧,比如你知道主頁的網頁地址,那么你直接訪問這個網址,就可以跳過登入了(可能是這樣的吧,我猜的
登入地址XXXXX/views/login.jsp
主頁地址XXXXX/views/index.jsp
那我們直接訪問主頁地址,就可以跳過登入了
相反現在:
登入地址XXXXX/views/login.jsp
我們需要訪問XXXXXX.do這個后端方法,返回主頁
但是瀏覽器的網頁還是顯示XXXXXX.do
我們不知道主頁的真正地址
所以可能大概也許就起到保密的作用了。
完整代碼
test.jsp 路徑: WEB-INF/views/login/test.jsp
<%--
Created by IntelliJ IDEA.
User: zwz
Date: 2020/2/17 0016
Time: 7:39
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path;
%>
<html>
<head>
<title></title>
</head>
<body>
<a href="<%=basePath%>/summary/test1.do">
<button>按鈕</button>
</a>
<h2>${msg}</h2>
</body>
</html>
web.xml 路徑:WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<welcome-file-list>
<welcome-file>/WEB-INF/views/login/test.jsp</welcome-file>
</welcome-file-list>
<!--配置spring的字符編碼過濾器 -->
<filter>
<filter-name>CharacterEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- spring 開始-->
<!-- 加載spring的過濾器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</context-param>
<listener><!-- 啟動web容器時,自動裝配spring-dao.xml-->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- spring 結尾-->
<!--配置springmvc的核心過濾器 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
<!-- 容器啟動自動加載springmvc.xml -->
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
spring-mvc.xml 路徑: src/main/resources/spring/springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/context/spring-tx.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 開啟注解掃描 -->
<context:component-scan base-package="ypc.zwz.controller"/>
<!-- 配置springmvc的驅動,並開啟了對JSON數據格式的支持 -->
<mvc:annotation-driven/>
<!-- 配置視圖解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
spring-dao.xml 地址: src/main/resources/spring/spring-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置注解掃描 -->
<context:component-scan base-package="ypc.zwz.service"/>
<!-- 加載數據庫配置文件 -->
<context:property-placeholder location="classpath:resource/jdbc.properties"/>
<!-- 數據庫連接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 配置數據庫連接池屬性 -->
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- c3p0連接池私有屬性 -->
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<!-- 關閉連接后不自動commit -->
<property name="autoCommitOnClose" value="false"/>
<!-- 獲取連接超時時間 -->
<property name="checkoutTimeout" value="10000"/>
<!-- 當獲取連接失敗后重新連接的次數 -->
<property name="acquireRetryAttempts" value="2" />
</bean>
<!-- 配置SqlSessionFactory對象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入數據庫連接池 -->
<property name="dataSource" ref="dataSource"/>
<!-- 啟用mybatis的別名配置 -->
<property name="typeAliasesPackage" value="ypc.zwz.pojo"/>
<!-- 掃描Mapper層的配置文件 -->
<property name="mapperLocations" value="classpath:ypc/zwz/mapper/*.xml"/>
</bean>
<!-- 啟用mybatis的接口代理開發模式(接口和Xml配置必須同名,並且在同一目錄下) -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="ypc.zwz.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
</beans>
ArticleController.java 路徑 :src/main/java/cn/ypc/controller/ArticleController.java
package ypc.zwz.controller;
import ypc.zwz.pojo.Summary;
import ypc.zwz.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping(value = "/summary")
public class ArticleController {
private ArticleService articleService;
@RequestMapping(value = "/test1")
public String te(@RequestParam(value = "pageCode", defaultValue = "1", required = false) int pageCode,@RequestParam(value = "pageSize", defaultValue = "3", required = false) int pageSize,HttpServletRequest request,Model model) {
Summary summary = articleService.findById(23);
String str = summary.getR_content();
model.addAttribute("msg",str);
return "login/test";
}
}
其余代碼和我之前做的周總結雲盤代碼一致,開源,點擊這里查看