GitHub | https://github.com/Web-Learn-GSF/Java_Learn_Examples |
---|---|
父工程 | Java_Framework_SpringMVC |
MVC是(Model、View、Controller的缩写)一种软件设计规范,将业务逻辑、数据、显示三者分离开来组织代码
MVC主要作用是降低了视图与业务逻辑间的双向耦合
模块 | 组成 |
---|---|
Model(模型) | 提供要展示的数据,可以认为是领域模型或JavaBean组件(包含数据和行为) |
View(视图) | 负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西 |
Controller(控制器) | 接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作 |
这一章将讲述两种创建Web项目的方法来回顾servlet:
Maven创建web项目,运行servlet
Maven创建jar项目,手动添加框架依赖,运行servlet**(还没调试通顺,后续有空继续整)**
同时也将讲述Tomcat9和Tomcat10在servlet包依赖上的不同
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13.1version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>6.0.9version>
dependency>
<dependency>
<groupId>org.apache.tomcatgroupId>
<artifactId>tomcat-servlet-apiartifactId>
<version>10.0.4version>
dependency>
<dependency>
<groupId>org.apache.tomcatgroupId>
<artifactId>tomcat-jsp-apiartifactId>
<version>10.0.4version>
dependency>
dependencies>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13.1version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>6.0.9version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>2.5version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>jsp-apiartifactId>
<version>2.2version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
dependencies>
Tomcat9及以前,servlet依赖包名是 javax.servlet;Tomcat10之后,servlet依赖包名是 jakarta.servlet
如若不注意版本匹配,启动Tomcat会爆出404问题
Module名字:Demo-01-ServletReview-MavenWebCreate
Module内容解释:
整体结构及后续代码
Tomcat版本为10的代码
package GSF.Example.Servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//取得参数
String method = req.getParameter("method");
if ("add".equals(method)){
req.getSession().setAttribute("msg","执行了add方法");
}
if ("delete".equals(method)){
req.getSession().setAttribute("msg","执行了delete方法");
}
//业务逻辑:暂无
//视图跳转
req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
Tomcat版本为9的代码
package GSF.Example.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//取得参数
String method = req.getParameter("method");
if ("add".equals(method)){
req.getSession().setAttribute("msg","执行了add方法");
}
if ("delete".equals(method)){
req.getSession().setAttribute("msg","执行了delete方法");
}
//业务逻辑:暂无
//视图跳转
req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
区别:包的名字
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head>
<title>Kuangshen</title>
</head>
<body>
${msg}
</body>
</html>
<%@ page isELIgnored="false" %>
,可以关闭对el表达式的禁止,实现从session域中获取数据Maven创建web项目,默认的web.xml文件内容
DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>HelloServletservlet-name>
<servlet-class>GSF.Example.Servlet.HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>HelloServletservlet-name>
<url-pattern>/userurl-pattern>
servlet-mapping>
web-app>
若是手动添加框架依赖,创建的web.xml
<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>HelloServletservlet-name>
<servlet-class>GSF.Example.Servlet.HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>HelloServletservlet-name>
<url-pattern>/userurl-pattern>
servlet-mapping>
web-app>
暂时没调试通顺
Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架
官方文档:https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/web.html#spring-web
Spring MVC特点
Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计。
DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁。
Spring的web框架围绕DispatcherServlet设计:
Spring MVC框架像许多其他MVC框架一样, 以请求为驱动 , 围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet (它继承自HttpServlet 基类)
实现部分:表示框架已经帮忙完成;虚线部分:表示需要我们手动编写的地方
步骤1:
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
步骤2:
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
步骤3:
步骤4:
步骤5:
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
步骤6:
<bean id="/hello" class="GSF.Example.Controller.HelloController"/>
步骤7:
步骤8:
步骤9:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
bean>
步骤10:
步骤11:
步骤12:
Module名字:Demo-02-SpringMVC-xml
整体结构图及后续写入代码
DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<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>
<bean id="/hello" class="GSF.Example.Controller.HelloController"/>
beans>
package GSF.Example.Controller;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
//注意:这里我们先导入Controller接口
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//ModelAndView 模型和视图
ModelAndView mv = new ModelAndView();
//封装对象,放在ModelAndView中。Model
mv.addObject("msg","HelloSpringMVC!");
//封装要跳转的视图,放在ModelAndView中
mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
return mv;
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
Kuangshen
${msg}
Module名称:Demo-02-SpringMVC-annotation
整体结构图及后续写入代码
<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>SpringMVCservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>SpringMVCservlet-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">
<context:component-scan base-package="GSF.Example.Controller"/>
<mvc:default-servlet-handler />
<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>
package GSF.Example.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/HelloController")
public class HelloController {
//真实访问地址 : 项目名/HelloController/hello
@RequestMapping("/hello")
public String sayHello(Model model){
//向模型中添加属性msg与值,可以在JSP页面中取出并渲染
model.addAttribute("msg","hello, SpringMVC");
//web-inf/jsp/hello.jsp
return "hello";
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
你好
${msg}
控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。
控制器负责解析用户的请求并将其转换为一个模型。
在Spring MVC中一个控制器类可以包含多个方法
在Spring MVC中,对于Controller的配置方式有很多种
Demo-03-SpringMVC-Controller_Restful
package GSF.Example.Controller;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.ui.Model;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class HelloController_Interface implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("msg", "hello, SpringMVC, Controller_Interface");
mv.setViewName("hello");
return mv;
}
}
package GSF.Example.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/controller")
public class HelloController_Annotation {
//真实访问地址 : 项目名/controller/hello
@RequestMapping("/annotation")
public String sayHello(Model model){
//向模型中添加属性msg与值,可以在JSP页面中取出并渲染
model.addAttribute("msg","hello,SpringMVC, Controller_Annotation");
//web-inf/jsp/hello.jsp
return "hello";
}
}
注解开发会更频繁,且高效
两个方法的跳转指向同一个jsp页面,视图复用,可以看出控制器和视图之间是弱耦合关系
用于映射url到控制器类或一个特定的处理程序方法
可用于类或方法上:
// 仅注解在方法上:localhost:8080 / 项目名 / h1
@Controller
public class TestController {
@RequestMapping("/h1")
public String test(){
return "test";
}
}
// 既注解在类上,也注解在方法上:localhost:8080 /项目名/ admin / h1
@Controller
@RequestMapping("/admin")
public class TestController {
@RequestMapping("/h1")
public String test(){
return "test";
}
}
Restful就是一个资源定位及资源操作的风格,不是标准也不是协议,只是一种风格
基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制
操作 | Restful | 传统 |
---|---|---|
增 | http://127.0.0.1/item,POST方法 | http://127.0.0.1/item/saveItem.action,POST方法 |
删 | http://127.0.0.1/item/1,DELETE方法 | http://127.0.0.1/item/deleteItem.action?id=1,GET方法或POST方法 |
改 | http://127.0.0.1/item,PUT方法 | http://127.0.0.1/item/updateItem.action,POST方法 |
查(单一) | http://127.0.0.1/item/,GET方法(不带参数) | http://127.0.0.1/item/queryItem.action?id=1,GET方法 |
查(全部) | http://127.0.0.1/item/1/,GET方法(带参数) | http://127.0.0.1/item/queryItem.action/all,GET方法 |
package GSF.Example.Restful;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class Restful {
@RequestMapping("/restful/{var1}/{var2}")
public String calculate(@PathVariable int var1, @PathVariable int var2, Model model){
int result = var1 + var2;
model.addAttribute("msg", "求和结果:" + result);
return "hello";
}
}
package GSF.Example.Restful;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class Restful_method {
//@RequestMapping(value = "/restful_method/{var1}/{var2}", method = {RequestMethod.POST})
@RequestMapping(value = "/restful_method/{var1}/{var2}")
@GetMapping
public String calculate(@PathVariable int var1, @PathVariable int var2, Model model){
int result = var1 + var2;
model.addAttribute("msg", "求和结果:" + result);
return "hello";
}
}
将url变量绑定到方法参数上
若url变量传入的类型和方法参数的类型不对应,会出现404无法访问,而不是在程序中出现类型不匹配异常
通过注解的形式,指定url的请求方法类型
@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping
Demo-04-SpringMVC-DataProcess_Redirection
package GSF.Example.ResultRedirection;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.mvc.Controller;
public class ModelAndView implements Controller {
@Override
public org.springframework.web.servlet.ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
org.springframework.web.servlet.ModelAndView mv = new org.springframework.web.servlet.ModelAndView();
mv.addObject("msg", "hello, Result Redirection, ModelAndView");
mv.setViewName("hello");
return mv;
}
}
springmvc-servlet中注册bean
addObject:写入数据
setViewName:设置要跳转的视图资源
package GSF.Example.ResultRedirection;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.io.IOException;
@Controller
public class ServletAPI {
@RequestMapping("servlet_redirection/test1")
public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
// 输出
rsp.getWriter().println("hello, Result Redirection, ServletAPI: rsp.getWriter().println");
}
@RequestMapping("servlet_redirection/test2")
// 重定向:禁止指向受保护的视图资源
public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
rsp.sendRedirect("/Result_Redirection/test2.jsp");
}
@RequestMapping("servlet_redirection/test3")
public void test3(HttpServletRequest req, HttpServletResponse rsp) throws IOException, ServletException {
// 请求转发:可以指向受保护的视图资源
req.setAttribute("msg", "hello, Result Redirection, ServletAPI: req.setAttribute, req.getRequestDispatcher");
req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req, rsp);
}
}
注意:该代码针对Tomcat10,servlet包名前缀是“jakarta”
test1:直接在响应结果中写入数据,支持html标签
test2:响应重定向,重新请求资源(禁止请求受保护资源)
test3:请求转发,请求和响应信息可以继续传递(可以请求受保护资源)
package GSF.Example.ResultRedirection;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
// 请求前需要先注释掉springmvc-servlet.xml的视图解析器
@Controller
public class SpringMVC_NoViewParser {
@RequestMapping("/springMvc_redirection/test1")
public String test1() {
// 转发
return "/index_1.jsp";
}
@RequestMapping("/springMvc_redirection/test2")
public String test2() {
// 转发
//return "forward:/index.jsp";
//return "forward:/index_1.jsp";
return "forward:/WEB-INF/jsp/hello.jsp";
}
@RequestMapping("/springMvc_redirection/test3")
public String test3() {
// 重定向:不让定向到受保护的视图资源内
//return "redirect:/index.jsp";
return "redirect:/WEB-INF/jsp/hello.jsp";
}
}
package GSF.Example.ResultRedirection;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.io.IOException;
@Controller
public class SpringMVC_ViewParser {
@RequestMapping("/springMvc_redirection_VP/test1")
public String test1() throws IOException {
// 转发:自动借助视图解析器补充前缀和后缀
// return "index_1"; // 不行
// return "/index_2"; // 行
return "/jsp/hello"; // 行
}
@RequestMapping("/springMvc_redirection_VP/test2")
public String test2() throws IOException {
// 重定向:不需要视图解析器,写全路径
return "redirect:/Result_Redirection/test2.jsp";
}
}
package GSF.Example.DataProcess;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/data_process")
public class ProcessSubmitData {
@RequestMapping("/same_name")
public String test1(String name){
System.out.println(name);
return "/jsp/hello";
}
@RequestMapping("/different_name")
public String test2(@RequestParam("username") String name){
System.out.println(name);
return "/jsp/hello";
}
@RequestMapping("/object")
public String test3(User user){
System.out.println(user);
return "/jsp/hello";
}
}
package GSF.Example.DataShow;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class ShowDataToView {
// 第一种:ModelAndView,参考ResultRedirection/ModelAndView
// ModelMap
@RequestMapping("/show_data")
public String test1(@RequestParam("username") String name, ModelMap model){
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
model.addAttribute("msg",name);
System.out.println(name);
return "/jsp/hello";
}
// Model
@RequestMapping("/show_data_2")
public String test2(@RequestParam("username") String name, Model model){
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
model.addAttribute("msg",name);
System.out.println(name);
return "/jsp/hello";
}
}
<filter>
<filter-name>encodingfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
package com.kuang.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;
}
}
Demo-05-SpringMVC-Json
JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串
var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的
var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串
var obj = JSON.parse('{"a": "Hello", "b": "World"}');
//结果是 {a: 'Hello', b: 'World'}
var json = JSON.stringify({a: 'Hello', b: 'World'});
//结果是 '{"a": "Hello", "b": "World"}'
1、导包
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.8version>
dependency>
2、建立Module,完成springmvc-servlet.xml、web.xml配置(大差不差,不再详细贴出代码)
package GSF.Example.Controller;
import GSF.Example.Pojo.User;
import GSF.Example.Utils.JsonUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
//@Controller // 使用Controller,需要在方法上添加@ResponseBody注解,保证返回json形式数据
@RestController // 使用RestController,保证返回的都是json形式数据
public class UserController {
@RequestMapping("/json1")
//@RequestMapping(value = "/json1",produces = "application/json;charset=utf-8") // 设置返回数据字符集,避免乱码
//@ResponseBody
public String json1() throws JsonProcessingException {
//创建一个jackson的对象映射器,用来解析数据
ObjectMapper mapper = new ObjectMapper();
//创建一个对象
User user = new User("秦疆1号", 3, "男");
//将我们的对象解析成为json格式
String str = mapper.writeValueAsString(user);
System.out.println(str);
//由于@ResponseBody注解,这里会将str转成json格式返回;十分方便
return str;
}
@RequestMapping("/json2")
public String json2() throws JsonProcessingException {
//创建一个jackson的对象映射器,用来解析数据
ObjectMapper mapper = new ObjectMapper();
//创建一个对象
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);
//将我们的对象解析成为json格式
String str = mapper.writeValueAsString(list);
return str;
}
// 默认返回一个时间戳,是一个lang整数值
@RequestMapping("/json3")
public String json3() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//创建时间一个对象,java.util.Date
Date date = new Date();
//将我们的对象解析成为json格式
String str = mapper.writeValueAsString(date);
return str;
}
// 通过定义返回时间的格式返回数据
@RequestMapping("/json4")
public String json4() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//不使用时间戳的方式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//自定义日期格式对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//指定日期格式
mapper.setDateFormat(sdf);
Date date = new Date();
String str = mapper.writeValueAsString(date);
return str;
}
@RequestMapping("/json5")
public String json5() throws JsonProcessingException {
Date date = new Date();
String json = JsonUtils.getJson(date); // 将代码抽出来,自定义一个工具类
return 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>
1、导包
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.60version>
dependency>
2、建立Module,完成springmvc-servlet.xml、web.xml配置(大差不差,不再详细贴出代码)
核心类 | 代表 | 解释 |
---|---|---|
JSONObject | 代表 json 对象 | JSONObject实现了Map接口,猜想 JSONObject底层操作是由Map实现的 JSONObject对应json对象,通过各种形式的get()方法可以获取json对象中的数据,也可利用诸如size(),isEmpty()等方法获取"键:值"对的个数和判断是否为空 其本质是通过实现Map接口并调用接口中的方法完成的 |
JSONArray | 代表 json 对象数组 | 内部是有List接口中的方法来完成操作的 |
JSON | 代表 JSONObject和JSONArray的转化 | JSON类源码分析与使用 主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化 |
package GSF.Example.Controller;
import GSF.Example.Pojo.User;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class FastJsonDemo {
public static void main(String[] args) {
//创建一个对象
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);
}
}
学一半,后边再说吧,有点学不明白
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能
过滤器 | 拦截器 |
---|---|
servlet规范中的一部分,任何java web工程都可以使用 | 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用 |
通过配置,可以对所有要访问的资源进行拦截 | 是AOP思想的具体应用,只会拦截访问的控制器方法,如果访问的是jsp/html/css/image/js是不会进行拦截的 |
package GSF.Example.Interceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
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="GSF.Example.Interceptor.MyInterceptor"/>
mvc:interceptor>
mvc:interceptors>
1、建立相关Module
2、导包
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.3.3version>
dependency>
3、springmvc-servlet.xml配置bean!!
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"/>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Hello World!
上传文件
上传单个文件,java原生代码实现
上传单个文件,调file.TransferTo保存文件代码
上传多个文件(多个文件选择框实现),调file.TransferTo保存文件代码
上传多个文件(单个文件选择框实现),调file.TransferTo保存文件代码
下载文件
java原生代码实现
点击下载
package GSF.Example.Controller;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Controller
public class FileController {
@RequestMapping("/upload")
public String fileUpload_onefile_manualsave(@RequestParam("file") MultipartFile file , HttpServletRequest request) throws IOException {
//获取文件名 : file.getOriginalFilename();
String uploadFileName = file.getOriginalFilename();
//如果文件名为空,直接回到首页!
if ("".equals(uploadFileName)){
return "redirect:/index.jsp";
}
System.out.println("上传文件名 : "+uploadFileName);
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
System.out.println(path);
//如果路径不存在,创建一个
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";
}
/*
* 采用file.Transto 来保存上传的文件
*/
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file") MultipartFile 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("/upload3") // 等价于 @RequestMapping(value = "/upload", method = RequestMethod.POST)
public String fileUpload(HttpServletRequest req, @RequestParam("file") MultipartFile[] files) throws IOException {
List<String> pathStrs = new ArrayList<String>();
if(files.length > 0){
//循环多次上传多个文件
for (MultipartFile file : files) {
if(!file.isEmpty()){
//上传路径保存设置
String path = req.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";
}
// 下载文件的步骤:
// 1、设置response响应头
// 2、读取文件:InputStream
// 3、写出文件:OutputStream
// 4、执行操作
// 5、关闭流(先开的流后关)
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
//要下载的图片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = "基础语法.jpg";
//1、设置response 响应头
response.reset(); //设置页面不缓存,清空buffer
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();
}
out.close();
input.close();
return null;
}
}