springMVC舊版文件地址:https://docs.spring.io/spring/docs/4.3.24.RELEASE/spring-framework-reference/html/overview.html#overview-distribution-zip
MVC是模型(Model)、檢視(View)、控制器(Controller)的簡寫,是一種軟體設計規範
Model:數據模型,提供要展示的數據,因此包含數據和行爲,可以認爲是領域模型或JavaBean元件(包含數據和行爲),不過現在一般都分離開來:Value Object(數據Dao)和服務層(行爲Service)。也就是模型提供了模型數據查詢和模型數據的狀態更新等功能,包括數據和業務
View:負責進行模型的展示,一般就是我們見到的用戶介面,客戶想看到的東西
Controller:接受使用者的請求,委託給模型進行處理(狀態改變),處理完畢後把返回的數據模型返回給檢視,由檢視負責展示,也就是說控制器做了排程員的工作
主要作用:降低檢視與業務邏輯間的雙向耦合
MVC不是一種設計模式,而是一種架構模式,不同的MVC存在差異
最典型的MVC就是JSP+servlet+javabean的模式
MVC框架要做的事情:
常見的伺服器端MVC框架:Struts、Spring MVC、ASP.NET MVC、Zend Framework、JSF
常見的前端MVC框架:vue、angularjs、react、backbone
由MVC演化出的另外一些模式:MVP、MVVM等
在Model2中,一個專案是分爲三部分的:檢視、控制、模型
執行過程:
職責分析:
Controller:取得表單數據、呼叫業務邏輯、轉向指定的頁面
Model:業務邏輯、儲存數據的狀態
View:顯示頁面
優點:不僅提高了程式碼的複用率和專案的擴充套件性,而且大大降低了專案的維護成本
面試題:自己所做的專案架構是設計好的還是演進的?
演進的!!!任何一個專案的發展都是從最初的架構簡單的小專案逐漸演化,更改架構
Alibaba演進過程:最初是一個小型的PHP專案,隨着使用者量增多,PHP無法承載大的併發量,改爲Java架構。當時因爲給IBM、Oracle支付費用太多,一個叫王堅的博士提出了去IOE,對數據庫的使用又回到了MySql,但是Ali對MySql又做了很多優化,後來發展出了AliSql和AliRedis等。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
if(method.equals("add")){
req.getSession().setAttribute("msg","執行了add方法");
}
if(method.equals("delete")){
req.getSession().setAttribute("msg","執行了delete方法");
}
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.Nana.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
Spring MVC是Spring Framework的一部分,是基於Java實現MVC的輕量級Web框架
特點:
Spring的web框架圍繞DispatcherServlet[排程Servlet]設計
DispacherServlet的作用是將請求分發到不同的處理器
從Spring2.5開始,使用Java5或者以上版本的使用者可以採用基於註解形式進行開發,十分簡潔
設定版:理解原理使用
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--關聯一個springmvc組態檔-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--啓動級別爲1-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<!--匹配所有請求-->
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
編寫SpringMVC的組態檔spring-mvc-servlet.xml
注意:官方名稱要求:[servletname]-servlet
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
在servlet.xml中新增處理對映器
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("msg", "HelloSpringMVC");
mv.setViewName("hello");
return mv;
}
}
<bean id="/hello" class="com.Nana.controller.HelloController"/>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
注意:如果是先建立空的maven專案再新增web支援,可能會出現404錯誤
排查步驟:
如果還有其他的問題,請記得沒有什麼是重建一個專案解決不了的
註解版:實際開發中使用
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--表示和伺服器一同開啓-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--掃描指定包下的元件,使得@COntroller註解生效,由IOC容器統一管理-->
<context:component-scan base-package="com.Nana.controller"/>
<!--使得SpringMVC不處理靜態資源,比如.css、.html、.js、.mp3、.mp4等-->
<mvc:default-servlet-handler/>
<!--要使得@RequestMapping註解生效需向上下文中注DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter範例-->
<!--annotation-driven設定幫我們自動完成上述兩個範例的注入-->
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
/*代表這個類會被Spring接管,被這個註解的類中的所有方法,如果返回型別是String,並且有具體頁面可以跳轉,就會被檢視解析器解析*/
@Controller
public class HelloController {
/*存取對映地址*/
@RequestMapping("/test")
public String hello(Model model){
/*向模型中新增屬性與值,可以在jsp頁面中取出*/
model.addAttribute("msg", "你跳轉成功啦");
return "hello";
}
}
SpringMVC原理圖:
SpringMVC流程圖:實線表示SpringMVC框架提供的技術,無須開發者實現,虛線表示需要開發者實現
假設請求的url爲http://localhost:8080/SpringMVC/hello
此url可拆分爲三部分:
- http://localhost:8080是伺服器的域名
- SpringMVC是部署在伺服器上的web站點
- hello表示控制器
綜上,此url表示請求位於伺服器localhost:8080上的SpringMVC站點的hello控制器
HandlerMapping爲處理器對映,由DispatcherServlet呼叫。使用HandlerMapping.HandlerMapping會根據請求url查詢Handler
HandlerExecution表示具體的Handler,主要作用是根據url查詢控制器
HandlerExecution將解析後的資訊傳遞給DispatcherServlet,如解析控制器對映等
HandlerAdapter表示處理器適配器,作用是按照特定的規則去執行Handler
Handler讓具體的Controller執行
Controller將具體的執行資訊返回給HandlerAdapter,如ModelAndView
HandlerAdapter將試圖邏輯名或模型傳遞給DispatcherServlet
DispatcherServlet呼叫檢視解析器(ViewResolver)來解析HandlerAdapter傳遞的邏輯檢視名
檢視解析器將解析的邏輯檢視名傳給DispaptcherServletServlelt
DispatcherServlet根據檢視解析器解析的檢視結果,呼叫具體的檢視
最終檢視呈現給使用者
@Controller
作用:負責解析使用者的請求並將其轉換爲一個模型
實現:可以通過介面定義或註解定義
@RequestMapping
RestFul就是一個資源定位及資源操作的風格,不是標準也不是協定,只是一種風格。基於這個風格設計的軟體可以更簡潔,更有層次,更易於實現快取等機制 機製
功能:
與傳統方式操作資源對比:
傳統方式:通過不同的參數來實現不同的效果,方法單一
RestFul方式:可以通過不同的請求方式來實現不同的效果,比如:地址相同功能不同
傳統方式從前端獲得參數:
@Controller
public class RestFulController {
@RequestMapping("/h1")
public String test(int a, int b, Model model){
int ans=a+b;
model.addAttribute("msg","a+b的和爲:"+ans);
return "hello";
}
}
存取:http://localhost:8080/h1?a=1&b=2
RestFul風格獲得參數:實參形參名稱相同,如果不相同可以使用@PathVariable("")給形參取別名
@Controller
public class RestFulController {
@RequestMapping("/h1/{a}/{b}")
public String test(@PathVariable int a, @PathVariable int b, Model model){
int ans=a+b;
model.addAttribute("msg","a+b的和爲:"+ans);
return "hello";
}
}
存取:http://localhost:8080/h1/1/2
RestFul相同地址不同功能的三種實現方式:
@RequestMapping(value="/h1/{a}/{b}" method=RequestMethod.GET)
@RequestMapping(path="/h1/{a}/{b}" method=RequestMethod.GET)
@GetMapping("/h1/{a}/{b}")
ModelAndView:設定ModelAndView物件,根據view的名稱和檢視解析器跳轉到指定頁面
頁面:{檢視解析器字首}+viewName+{檢視解析器後綴}
<!--檢視解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("msg", "HelloSpringMVC");
mv.setViewName("hello");
return mv;
}
ServletAPI:通過設定ServletAPI,不需要檢視解析器
@Controller
public class ModelTest1 {
@RequestMapping("/h1")
public void test1(HttpServletRequest req, HttpServletResponse resp){
resp.getWriter().println("test");
}
@RequestMapping("/h2")
public void test2(HttpServletRequest req, HttpServletResponse resp){
resp.sendRedirect("/WEB-INF/jsp/hello.jsp");
}
@RequestMapping("/h3")
public void test3(HttpServletRequest req, HttpServletResponse resp){
req.setAttribute("msg","test")
req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);
}
}
SpringMVC:通過SpringMVC來實現轉發和重定向,無需檢視解析器
本質是重新請求一個地方,注意路徑問題
@Controller
public class ResultSpringMVC{
@RequestMapping("/h1")
public String test1(){
return "/WEB-INF/jsp/hello.jsp"
}
@RequestMapping("/h2")
public String test2(){
return "forward:/WEB-INF/jsp/hello.jsp"
}
@RequestMapping("/h3")
public String test3(){
return "redirect:/WEB-INF/jsp/hello.jsp"
}
}
1. 提交數據和處理方法參數名一致
提交數據:http://localhost:8080/test?hello=test
處理方法:
@Controller
public class UserController {
@RequestMapping("/test")
public void test(String hello){
System.out.println(hello);
}
}
後臺輸出:test
2. 提交數據和處理方法參數名不一致
提交數據:http://localhost:8080/test?userHello=test
處理方法:
@Controller
public class UserController {
@RequestMapping("/test")
public void test(@RequestParam("userHello")String hello){
System.out.println(hello);
}
}
後臺輸出:test
3.提交的是一個物件
提交數據:http://localhost:8080/user?id=1&name=%E6%B5%B7%E7%87%95%E9%85%B1&age=21
處理方法:
@Controller
public class UserController {
@RequestMapping("/user")
public void test(User user){
System.out.println(user);
}
}
後臺輸出:User{id=1, name=‘海燕醬’, age=21}
注意:
1.通過ModelAndView
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("msg", "HelloSpringMVC");
mv.setViewName("hello");
return mv;
}
2.通過Model
@RequestMapping("/test")
public String hello(Model model){
model.addAttribute("msg", "HelloSpringMVC");
return "hello";
}
3.通過ModelMap
@RequestMapping("/test")
public String hello(ModelMap model){
model.addAttribute("msg", "HelloSpringMVC");
return "hello";
}
三種方式對比:
測試程式碼:hello頁面只負責取msg數據
<form action="/e1" method="post">
<input type="text" name="name">
<input type="submit">
</form>
@Controller
public class EncodingController {
@RequestMapping("/e1")
public String test(String name, Model model){
model.addAttribute("msg",name);
return "hello";
}
}
測試數據:
測試結果:
解決方式一:自己寫編碼過濾器
public class EncodingFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException { }
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
filterChain.doFilter(servletRequest,servletResponse);
}
public void destroy() { }
}
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.Nana.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
缺點:不夠強大
解決方式二:使用SpringMVC編碼過濾器
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
缺點:某些極端情況下,這個過濾器對get支援不好
解決方式三:使用別人寫好的過濾器
修改tomcat組態檔,設定編碼
<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
自定義過濾器
package com.Nana.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* 解決get和post請求 全部亂碼的過濾器
*/
public class GenericEncodingFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//處理response的字元編碼
HttpServletResponse myResponse=(HttpServletResponse) response;
myResponse.setContentType("text/html;charset=UTF-8");
// 轉型爲與協定相關物件
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 對request包裝增強
HttpServletRequest myrequest = new MyRequest(httpServletRequest);
chain.doFilter(myrequest, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
//自定義request物件,HttpServletRequest的包裝類
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
//是否編碼的標記
private boolean hasEncode;
//定義一個可以傳入HttpServletRequest物件的建構函式,以便對其進行裝飾
public MyRequest(HttpServletRequest request) {
super(request);// super必須寫
this.request = request;
}
// 對需要增強方法 進行覆蓋
@Override
public Map getParameterMap() {
// 先獲得請求方式
String method = request.getMethod();
if (method.equalsIgnoreCase("post")) {
// post請求
try {
// 處理post亂碼
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else if (method.equalsIgnoreCase("get")) {
// get請求
Map<String, String[]> parameterMap = request.getParameterMap();
if (!hasEncode) { // 確保get手動編碼邏輯只執行一次
for (String parameterName : parameterMap.keySet()) {
String[] values = parameterMap.get(parameterName);
if (values != null) {
for (int i = 0; i < values.length; i++) {
try {
// 處理get亂碼
values[i] = new String(values[i]
.getBytes("ISO-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
hasEncode = true;
}
return parameterMap;
}
return super.getParameterMap();
}
//取一個值
@Override
public String getParameter(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
if (values == null) {
return null;
}
return values[0]; // 取回參數的第一個值
}
//取所有值
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
return values;
}
}
在web.xml中設定這個過濾器
/和/*區別:
/會匹配到/springmvc這樣的路徑型url,不會匹配到模式爲*.jsp這樣的後綴型url
會匹配所有的url:路徑型的和後綴型的url(包括/springmvc,.jsp,.js和*.html等)
兩個符號要慎重選用
JSON(JavaScript Object Notation,JS物件標記)是一種輕量級的數據交換格式,目前使用特別廣泛
特點:
採用完全獨立於程式語言的文字格式來儲存和表示數據
簡潔和清晰的層次結構使得JSON成爲理想的數據交換語言
易於人閱讀和編寫,同時也易於機器解析和生成,並有效地提升網路傳輸效率
數據型別:
要求和語法格式:
{"name":"海燕醬"}
{"age":"21"}
和JavaScript物件關係:
var obj = {a: 'Hello', b: 'World'}; //這是一個物件,注意鍵名也是可以使用引號包裹的
var json = '{"a": "Hello", "b": "World"}'; //這是一個 JSON 字串,本質是一個字串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--script標籤沒有自閉合-->
<script type="text/javascript">
//編寫一個JavaScript物件
var user = {
name:"海燕醬",
age:3,
sex:"女"
};
//將js物件轉換爲json物件
var json = JSON.stringify(user);
console.log(json);
//將json物件轉換爲js物件
var obj = JSON.parse(json);
console.log(obj);
</script>
</head>
<body>
</body>
</html>
測試結果:
Jackson使用:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.0</version>
</dependency>
/*如果使用@RestController可以使得所有的方法都返回json字串,不用每個方法都加@ResponseBody了*/
@Controller
public class UserController {
@RequestMapping("/u1")
/*@ResponseBody不會走檢視解析器,會直接返回一個字串*/
@ResponseBody
public String json() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
User user = new User("海燕醬", 21, "女");
String str = mapper.writeValueAsString(user);
return str;
}
}
中文亂碼問題解決:
方式一:在對映的時候改變編碼方式
@RequestMapping(value ="/u1",produces = "application/json;charset=utf-8")
測試結果:
方法二:在springmvc-servlet中進行統一設定
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
Fastjson三個主要的類:
Fastjson使用:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
@RestController
public class UserController {
@RequestMapping(value ="/u1",produces = "application/json;charset=utf-8")
public String json() throws JsonProcessingException {
//建立一個物件
User user1 = new User("海燕醬1號", 3, "女");
User user2 = new User("海燕醬2號", 3, "女");
User user3 = new User("海燕醬3號", 3, "女");
User user4 = new User("海燕醬4號", 3, "女");
List<User> list = new ArrayList<User>();
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
System.out.println("*******Java物件 轉 JSON字串*******");
String str1 = JSON.toJSONString(list);
System.out.println("JSON.toJSONString(list)==>"+str1);
String str2 = JSON.toJSONString(user1);
System.out.println("JSON.toJSONString(user1)==>"+str2);
System.out.println("\n****** JSON字串 轉 Java物件*******");
User jp_user1=JSON.parseObject(str2,User.class);
System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);
System.out.println("\n****** Java物件 轉 JSON物件 ******");
JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));
System.out.println("\n****** JSON物件 轉 Java物件 ******");
User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);
return "hello";
}
}
CREATE DATABASE `ssmbuild`;
USE `ssmbuild`;
DROP TABLE IF EXISTS `books`;
CREATE TABLE `books` (
`bookID` INT(10) NOT NULL AUTO_INCREMENT COMMENT '書id',
`bookName` VARCHAR(100) NOT NULL COMMENT '書名',
`bookCounts` INT(11) NOT NULL COMMENT '數量',
`detail` VARCHAR(200) NOT NULL COMMENT '描述',
KEY `bookID` (`bookID`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)VALUES
(1,'Java',1,'從入門到放棄'),
(2,'MySQL',10,'從刪庫到跑路'),
(3,'Linux',5,'從進門到進牢');
<dependencies>
<!--Junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--數據庫驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- 數據庫連線池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!--Servlet - JSP -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--Mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--低版本會報錯,報錯的話升版本然後多啓動幾次就可以了-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
建立基本的目錄結構,編寫基礎的mybatis組態檔mybatis-config.xml和spring組態檔applictaionContext.xml檔案
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Books {
private int bookID;
private String bookName;
private int bookCounts;
private String details;
}
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
public interface BookMapper {
int addBook(Books book);
int deleteBookById(@Param("bookId")int id);
int updateBook(Books book);
Books queryBookById(@Param("bookId")int id);
List<Books> queryAllBook();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper>
<insert id="addBook" parameterType="Books">
insert into books(bookName,bookCounts,detail)
values(#{bookName},#{bookCounts},#{detail})
</insert>
<delete id="deleteBookById" parameterType="int">
delete from books where bookID=#{bookId}
</delete>
<update id="updateBook" parameterType="Books">
update books set bookNamed=#{bookName},bookCounts=#{bookCounts},detail=#{detail}
where bookID=#{bookID}
</update>
<select id="queryBookById" parameterType="int">
select * from books where bookID=#{bookId}
</select>
<select id="queryAllBook">
select * from books
</select>
</mapper>
<typeAliases>
<package name="com.Nana.pojo"/>
</typeAliases>
<mappers>
<mapper class="com.Nana.dao.BookMapper"/>
</mappers>
public interface BookService {
int addBook(Books book);
int deleteBookById(int id);
int updateBook(Books book);
Books queryBookById(int id);
List<Books> queryAllBook();
}
public class BookServiceImpl implements BookService{
BookMapper bookMapper;
public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}
public int addBook(Books book) {
return bookMapper.addBook(book);
}
public int deleteBookById(int id) {
return bookMapper.deleteBookById(id);
}
public int updateBook(Books book) {
return updateBook(book);
}
public Books queryBookById(int id) {
return bookMapper.queryBookById(id);
}
public List<Books> queryAllBook() {
return bookMapper.queryAllBook();
}
}
整合Mybatis層結束
<?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
https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.關聯數據庫組態檔-->
<context:property-placeholder location="classpath:db.properties"/>
<!--2.設定連線池
dbcp:半自動化操作,不能自動連線
c3p0:自動化操作(自動化的載入組態檔,並且可以自動設定到物件中)
druid:hikari
-->
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8"/>
<property name="user" value="root"/>
<property name="password" value="123456"/>
<!--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>
<!--3.獲得sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!--4.設定dao介面掃描包,動態實現Dao介面可以注入到Spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<property name="basePackage" value="com.Nana.dao"/>
</bean>
</beans>
<?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
https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.掃描service下的包-->
<context:component-scan base-package="com.Nana.service"/>
<!--2.將所有的業務類注入到Spring-->
<bean id="BookServiceImpl" class="com.Nana.service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/>
</bean>
<!--3.宣告式事務設定-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"/>
</bean>
<!--4.aop事務支援-->
</beans>
整合Spring層結束
<?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: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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.註解驅動-->
<mvc:annotation-driven/>
<!--2.靜態資源過濾-->
<mvc:default-servlet-handler/>
<!--3.掃描包controller-->
<context:component-scan base-package="com.Nana.controller"/>
<!--4.檢視解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
<!--設定DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--亂碼過濾-->
<filter>
<filter-name>encodingFilter</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>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--session存活時間-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
<import resource="spring-dao.xml"/>
<import resource="spring-service.xml"/>
<import resource="spring-mvc.xml"/>
整合SpringMVC層結束
//BookMapper.java
public interface BookMapper {
int addBook(Books book);
int deleteBookById(@Param("bookId")int id);
int updateBook(Books book);
Books queryBookById(@Param("bookId")int id);
List<Books> queryAllBook();
}
<!--BookMapper.xml-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.Nana.dao.BookMapper">
<insert id="addBook" parameterType="Books">
insert into books(bookName,bookCounts,detail)
values(#{bookName},#{bookCounts},#{detail})
</insert>
<delete id="deleteBookById" parameterType="int">
delete from books where bookID=#{bookId}
</delete>
<update id="updateBook" parameterType="Books">
update books set bookName=#{bookName},bookCounts=#{bookCounts},detail=#{detail}
where bookID=#{bookID}
</update>
<select id="queryBookById" parameterType="int" resultType="Books">
select * from books where bookID=#{bookId}
</select>
<select id="queryAllBook" resultType="Books">
select * from books
</select>
</mapper>
//BookService.java
public interface BookService {
int addBook(Books book);
int deleteBookById(int id);
int updateBook(Books book);
Books queryBookById(int id);
List<Books> queryAllBook();
}
//BookServiceImpl.java
public class BookServiceImpl implements BookService{
BookMapper bookMapper;
public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}
public int addBook(Books book) {
return bookMapper.addBook(book);
}
public int deleteBookById(int id) {
return bookMapper.deleteBookById(id);
}
public int updateBook(Books book) {
return bookMapper.updateBook(book);
}
public Books queryBookById(int id) {
return bookMapper.queryBookById(id);
}
public List<Books> queryAllBook() { return bookMapper.queryAllBook(); }
public Books queryBookByName(String bookName){return bookMapper.queryBookByName(bookName);}
}
使用BootStrap視覺化佈局系統可以輔助前端程式碼編寫
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>書籍展示</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>書籍列表--------顯示所有書籍</small>
</h1>
</div>
</div>
<div class="row">
<div class="col-md-4 column">
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toAddBook">新增書籍</a>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/allBook">顯示全部書籍</a>
</div>
<div class="col-md-8 column">
<form class="form-inline" action="${pageContext.request.contextPath}/book/queryBook" method="post" style="float:right">
<span style="color:red; font-weight: bold">${error}</span>
<input type="text" name="queryBookName" class="form-control" placeholder="請輸入要查詢的書籍名稱">
<input type="submit" value="查詢" class="btn btn-primary">
</form>
</div>
</div>
</div>
<div class="row clearfix">
<div class="col-md-12 column">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>書籍編號</th>
<th>書籍名稱</th>
<th>書籍數量</th>
<th>書籍詳情</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach var="book" items="${list}">
<tr>
<td>${book.bookID}</td>
<td>${book.bookName}</td>
<td>${book.bookCounts}</td>
<td>${book.detail}</td>
<td>
<a href="${pageContext.request.contextPath}/book/toUpdateBook?id=${book.bookID}">修改</a>
  |  
<a href="${pageContext.request.contextPath}/book/deleteBook?id=${book.bookID}">刪除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
@Controller
@RequestMapping("/book")
public class BookController {
@Autowired
@Qualifier("BookServiceImpl")
private BookService bookService;
@RequestMapping("/allBook")
public String list(Model model){
List<Books> list = bookService.queryAllBook();
model.addAttribute("list",list);
return "allBook";
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>新增書籍</small>
</h1>
</div>
</div>
</div>
<form action="/book/addBook" method="post">
<div class="form-group">
<label>書籍名稱:</label>
<input type="text" name="bookName" class="form-control" required="required">
</div>
<div class="form-group">
<label>書籍數量:</label>
<input type="text" name="bookCounts" class="form-control" required="required">
</div>
<div class="form-group">
<label>書籍描述:</label>
<input type="text" name="detail" class="form-control" required="required">
</div>
<div class="form-group">
<input type="submit" class="form-control" value="提交">
</div>
</form>
</div>
</body>
</html>
@RequestMapping("/toAddBook")
public String toAddPaper(){
return "addBook";
}
@RequestMapping("/addBook")
public String addBook(Books book){
bookService.addBook(book);
return "redirect:/book/allBook";
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>修改書籍</small>
</h1>
</div>
</div>
</div>
<form action="/book/updateBook" method="post">
<input type="hidden" name="bookID" value="${QBook.bookID}">
<div class="form-group">
<label>書籍名稱:</label>
<input type="text" name="bookName" value=${QBook.bookName} class="form-control" required="required">
</div>
<div class="form-group">
<label>書籍數量:</label>
<input type="text" name="bookCounts" value="${QBook.bookCounts}" class="form-control" required="required">
</div>
<div class="form-group">
<label>書籍描述:</label>
<input type="text" name="detail" value="${QBook.detail}" class="form-control" required="required">
</div>
<div class="form-group">
<input type="submit" class="form-control" value="修改">
</div>
</form>
</div>
</body>
</html>
@RequestMapping("/toUpdateBook")
public String toUpdateBook(int id ,Model model){
Books book = bookService.queryBookById(id);
model.addAttribute("QBook",book);
return "updateBook";
}
@RequestMapping("/updateBook")
public String updateBook(Books book){
bookService.updateBook(book);
return "redirect:/book/allBook";
}
@RequestMapping("/deleteBook")
public String toDeleteBook(int id, Model model){
bookService.deleteBookById(id);
return "redirect:/book/allBook";
}
//BookMapper.java
Books queryBookByName(String bookName);
<!--BookMapper.xml-->
<select id="queryBookByName" resultType="Books">
select * from books where bookName=#{bookName}
</select>
//BookService.java
Books queryBookByName(String bookName);
//BookServiceImpl.java
public Books queryBookByName(String bookName){return bookMapper.queryBookByName(bookName);}
//BookController.java
@RequestMapping("/queryBook")
public String queryBook(String queryBookName, Model model){
Books book=bookService.queryBookByName(queryBookName);
List<Books> list = new ArrayList<Books>();
list.add(book);
if(book==null){
list=bookService.queryAllBook();
model.addAttribute("error","未找到");
}
model.addAttribute("list",list);
return "allBook";
}
AJAX(Asynchronous JavaScript and XML,非同步的JavaScript和XML)。是一種在無需重新載入整個網頁的情況下,能夠更新部分網頁的技術。不是一種新的程式語言,而是一種用於建立更好更快以及互動性更強的Web應用程式的技術
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>僞造Ajax</title>
</head>
<body>
<script type="text/javascript">
window.onload = function f() {
var myDate = new Date();
document.getElementById('currentTime').innerText = myDate.getTime();
}
function loadPage() {
var targetURL = document.getElementById('url').value;
console.log(targetURL);
document.getElementById('iframePosition').src=targetURL;
}
</script>
<div>
<p>請輸入要載入的地址:<span id="currentTime"></span></p>
<p>
<input type="text" id="url" value="https://www.baidu.com/">
<input type="button" value="提交" onclick="loadPage()">
</p>
</div>
<div>
<h3> 載入頁面的位置: </h3>
<iframe style="width:100%; height:500px" id="iframePosition"></iframe>
</div>
</body>
</html>
Ajax的核心是XMLHttpRequest物件(XHR),XHR爲向伺服器發送請求和解析伺服器響應提供了介面,能夠以非同步方式從伺服器獲取新數據
jQuery Ajax作用:能夠使用HTTP Get和HTTP Post從遠端伺服器上請求文字、HTML、XML或JSON,同時可以把外部數據直接載入網頁的被選元素中
jQuery Ajax本質:對XMLHttpRequest進行了封裝,便於呼叫
jQuery Ajax部分參數:
jQuery.ajax(...)
url:請求地址
type:請求方式,GET、POST(1.9.0之後用method)
headers:請求頭
data:要發送的數據
contentType:即將發送資訊至伺服器的內容編碼型別(預設: "application/x-www-form-urlencoded; charset=UTF-8")
async:是否非同步
timeout:設定請求超時時間(毫秒)
beforeSend:發送請求前執行的函數(全域性)
complete:完成之後執行的回撥函數(全域性)
success:成功之後執行的回撥函數(全域性)
error:失敗之後執行的回撥函數(全域性)
accepts:通過請求頭髮送給伺服器,告訴伺服器當前用戶端可接受的數據型別
dataType:將伺服器端返回的數據轉換成指定型別
"xml": 將伺服器端返回的內容轉換成xml格式
"text": 將伺服器端返回的內容轉換成普通文字格式
"html": 將伺服器端返回的內容轉換成普通文字格式,在插入DOM中時,如果包含JavaScript標籤,則會嘗試去執行。
"script": 嘗試將返回值當作JavaScript去執行,然後再將伺服器端返回的內容轉換成普通文字格式
"json": 將伺服器端返回的內容轉換成相應的JavaScript物件
"jsonp": JSONP 格式使用 JSONP 形式呼叫函數時,如 "myurl?callback=?" jQuery 將自動替換 ? 爲正確的函數名,以執行回撥函數
jQuery.ajax()測試:
<?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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.Nana.controller"/>
<mvc:default-servlet-handler/>
<!--處理JSON亂碼問題-->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
下載網址:https://jquery.com/download/
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.5.1.js"></script>
<head>
<title>$Title$</title>
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.5.1.js"></script>
<script>
function a() {
$.post({
url:"${pageContext.request.contextPath}/t1",
data:{"name":$("#username").val()},
success:function (data) {
alert(data);
}
})
}
</script>
</head>
<body>
使用者名稱:<input type="text" id="username" οnblur="a()">
</body>
@RestController
public class AjaxController {
@RequestMapping("/t1")
public void test(String name, HttpServletResponse resp) throws IOException {
System.out.println(name);
if("海燕醬".equals(name)){
resp.getWriter().print("true");
}
else{
resp.getWriter().print("false");
}
}
}
Ajax非同步載入數據測試:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.5.1.js"></script>
<script>
$(function () {
$("#btn").click(function () {
$.post("${pageContext.request.contextPath}/t2",function (data) {
var html="";
for(let i=0; i<data.length; i++){
html+="<tr>"
+"<td>"+data[i].name+"</td>"
+"<td>"+data[i].age+"</td>"
+"<td>"+data[i].sex+"</td>"
+"</tr>"
}
$("#content").html(html);
});
})
});
</script>
</head>
<body>
<input type="button" value="載入數據" id="btn">
<table>
<tr>
<td>姓名</td>
<td>年齡</td>
<td>性別</td>
</tr>
<tbody id="content"></tbody>
</table>
</body>
</html>
@RequestMapping("/t2")
public List<User> test2(){
List<User> list = new ArrayList<User>();
list.add(new User("Java",1,"男"));
list.add(new User("前端",1,"女"));
list.add(new User("運維",1,"男"));
return list;
}
啓動測試:
Ajax動態驗證使用者名稱密碼測試:
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.5.1.js"></script>
<script>
function a1() {
$.post({
url:"${pageContext.request.contextPath}/t3",
data:{"name":$("#name").val()},
success:function (data) {
if(data.toString()==='ok'){
$("#userInfo").css("color","green");
}
else{
$("#userInfo").css("color","red");
}
$("#userInfo").html(data);
}
})
}
function a2() {
$.post({
url:"${pageContext.request.contextPath}/t3",
data:{"pwd":$("#pwd").val()},
success:function (data) {
if(data.toString()==='ok'){
$("#pwdInfo").css("color","green");
}
else{
$("#pwdInfo").css("color","red");
}
$("#pwdInfo").html(data);
}
})
}
</script>
</head>
<body>
<p>
使用者名稱:<input type="text" id="name" οnblur="a1()">
<span id="userInfo"></span>
</p>
<p>
密碼:<input type="text" id="pwd" οnblur="a2()">
<span id="pwdInfo"></span>
</p>
</body>
</html>
@RequestMapping("/t3")
public String test3(String name, String pwd){
String msg="";
if(name!=null){
if("admin".equals(name)){
msg = "ok";
}
else{
msg = "使用者名稱有誤";
}
}
if(pwd!=null){
if("123456".equals(pwd)){
msg = "ok";
}
else{
msg = "密碼有誤";
}
}
return msg;
}
測試結果:
作用:SpringMVC的攔截器類似於Servlet開發中的過濾器Filter,用於對處理器進行預處理和後處理。開發者可以自己定義一些攔截器來實現特定的功能
與過濾器區別:
自定義攔截器必須實現HandlerInterceptor介面
自定義攔截器使用:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
<?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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.Nana.controller"/>
<mvc:default-servlet-handler/>
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
public class MyInterceptor implements HandlerInterceptor {
//在請求處理的方法之前執行
//如果返回true執行下一個攔截器
//如果返回false就不執行下一個攔截器
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("------------處理前------------");
return true;
}
//在請求處理方法執行之後執行
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("------------處理後------------");
}
//在dispatcherServlet處理後執行,做清理工作.
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("------------清理------------");
}
}
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.Nana.config.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
@RestController
public class TestController {
@RequestMapping("/t1")
public String test(){
System.out.println("方法執行了");
return "hello";
}
}
使用者登錄攔截實現:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>首頁</h1>
<hr>
<a href="${pageContext.request.contextPath}/user/jumplogin">登錄</a>
<a href="${pageContext.request.contextPath}/user/jumpSuccess">成功頁面</a>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<h1>登錄頁面</h1>
<hr>
<body>
<form action="${pageContext.request.contextPath}/user/login">
使用者名稱:<input type="text" name="username"> <br>
密碼:<input type="password" name="pwd"> <br>
<input type="submit" value="提交">
</form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>登錄成功頁面</h1>
<hr>
${user}
<a href="${pageContext.request.contextPath}/user/logout">註銷</a>
</body>
</html>
public class LoginInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
// 如果是登陸頁面則放行
System.out.println("uri: " + request.getRequestURI());
if (request.getRequestURI().contains("login")) {
return true;
}
HttpSession session = request.getSession();
// 如果使用者已登陸也放行
if(session.getAttribute("user") != null) {
return true;
}
// 使用者沒有登陸跳轉到登陸頁面
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
return false;
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { }
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { }
}
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean id="loginInterceptor" class="com.Nana.config.LoginInterceptor"/>
</mvc:interceptor>
在2003年,Apache Software Foundation發佈了開源的Commons FileUpload元件,很快成爲Servlet/JSP程式設計師上傳檔案的最佳選擇。Servlet3.0規範已經提供方法來處理檔案上傳,但這種上傳需要在Servlet中完成,SpringMVC則進行了簡單的封裝。
SpringMVC使用FileUpload技術實現了一個MultipartResolver實現類CommonMultipartResolver進行檔案上傳,MultipartResolver是隨插即用的
檔案上傳實現:
<!--檔案上傳-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<!--servlet-api匯入高版本的-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
SpringMVC可以很好地支援檔案上傳,但是SpringMVC上下文中預設沒有裝配MultipartPart,因此預設情況下不能處理檔案上傳工作。如果想使用此功能,需在上下文中設定MultipartResolver
注意:bean的id必須爲multipartResolver,否則上傳檔案會報400錯誤
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 請求的編碼格式,必須和jSP的pageEncoding屬性一致,以便正確讀取表單的內容,預設爲ISO-8859-1 -->
<property name="defaultEncoding" value="utf-8"/>
<!-- 上傳檔案大小上限,單位爲位元組(10485760=10M) -->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
注意:如果需要上傳檔案的話,必須將表單的method設定爲POST,並將enctype設定爲multipart/form-data。只有在這樣的情況下,瀏覽器纔會把使用者選擇的檔案以二進制數據發送給伺服器
表單中enctype屬性介紹:
application/x-www=form-urlencoded:預設方式,只處理表單域中的 value 屬性值,採用這種編碼方式的表單會將表單域中的值處理成 URL 編碼方式
multipart/form-data:這種編碼方式會以二進制流的方式來處理表單數據,這種編碼方式會把檔案域指定檔案的內容也封裝到請求參數中,不會對字元編碼
text/plain:除了把空格轉換爲 「+」 號外,其他字元都不做編碼處理,這種方式適用直接通過表單發送郵件
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload">
</form>
@Controller
public class FileController {
//@RequestParam("file") 將name=file控制元件得到的檔案封裝成CommonsMultipartFile 物件
//批次上傳CommonsMultipartFile則爲陣列即可
@RequestMapping("/upload")
public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {
//獲取檔名
String uploadFileName = file.getOriginalFilename();
if ("".equals(uploadFileName)){
return "redirect:/index.jsp";
}
System.out.println("上傳檔名 : "+uploadFileName);
//獲得上傳路徑
String path = request.getServletContext().getRealPath("/upload");
//如果路徑不存在,建立一個
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
System.out.println("上傳檔案儲存地址:"+realPath);
InputStream is = file.getInputStream(); //檔案輸入流
OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //檔案輸出流
//讀取寫出
int len=0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}
}
檔案上傳儲存實現:
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//上傳路徑儲存設定
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//上傳檔案地址
System.out.println("上傳檔案儲存地址:"+realPath);
//通過CommonsMultipartFile的方法直接寫檔案(注意這個時候)
file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));
return "redirect:/index.jsp";
}
下載檔案步驟:
下載檔案實現:
注意:要使用正確的檔案路徑和檔名,記得加後綴名
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
//要下載的圖片路徑和名稱
String path = request.getServletContext().getRealPath("/upload");
String fileName = "TIM截圖20190430231748.png";
//1、設定response 響應頭
//設定頁面不快取,清空buffer
response.reset();
//設定字元編碼
response.setCharacterEncoding("UTF-8");
//使用二進制傳輸數據
response.setContentType("multipart/form-data");
//設定響應頭
response.setHeader("Content-Disposition",
"attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));
File file = new File(path,fileName);
//2、使用輸入流讀取檔案
InputStream input=new FileInputStream(file);
//3、使用輸出流寫出檔案
OutputStream out = response.getOutputStream();
byte[] buff =new byte[1024];
int index=0;
//4、執行寫出操作
while((index= input.read(buff))!= -1){
out.write(buff, 0, index);
out.flush();
}
//5、關閉流
out.close();
input.close();
return null;
}
<a href="/download">點選下載</a>