# ceshi
**Repository Path**: Answersz/ceshi
## Basic Information
- **Project Name**: ceshi
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-06-23
- **Last Updated**: 2025-06-23
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## SpringMVC
#### ssm:mybatis+Spring+SpringMVC MVC三层架构
**1.什么是MVC:**
> MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范
>
> **Servlet处理:**
>
> 1. 用户发请求
> 2. Servlet接受请求数据,并调用对应的业务逻辑方法
> 3. 业务处理完毕,返回更新后的数据给servlet
> 4. servlet转向JSP,由JSP来渲染页面
> 5. 响应给前端更新后的页面
>
> **mvc:**
>
> Controller层:
>
> 1. 取得表单数据
> 2. 调用业务逻辑
> 3. 转向指定的页面
>
> Model层:
>
> 1. 业务逻辑
> 2. 保存数据的状态
>
> View 视图:
>
> 1. 显示页面
### 1 回顾Servlet
1. 直接创建Maven项目,不需要添加其他工程
2. 导入父依赖
```xml
junit
junit
4.13.2
test
org.springframework
spring-webmvc
5.3.12
javax.servlet
servlet-api
2.5
javax.servlet
jstl
1.2
```
3.添加为web项目


**步骤:**
- 创建java类继承HttpServlet
- 重写doGet和doPost方法
```java
package com.smile.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 {
//1.获取前端参数
String method = req.getParameter("method");
if (method.equals("add")){
req.getSession().setAttribute("msg","执行了add方法");
}
if (method.equals("delete")){
req.getSession().setAttribute("msg","执行了delete方法");
}
//2.调用业务层
//3.视图转发或重定向
req.getRequestDispatcher("/WEB-INF/jsp/text.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
```
- 在web.xml中配置
```xml
hello
com.smile.servlet.HelloServlet
hello
/hello
index.jsp
```
### 2 中心控制器(DispatcherServlet)
Spring的web框架围绕DispatcherServlet设计,DispatcherServlet的作用是将请求分发到不同的处理器。从Spring2.5开始,使用Java5或者以上版本用户可以采用基于注解@Controller声明方式。
#### 2.1 SpringMVC的原理如下图所示:
当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。

#### 2.2 SpringMVC执行原理

图为SpringMVC的一个较完整的流程图,实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线表示需要开发者实现。
简要分析执行流程
DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
我们假设请求的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查找控制器,如上url被查找控制器为:hello。
>
> HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
>
> HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
>
> Handler让具体的Controller执行。
>
> Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
>
> HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
>
> DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
>
> 视图解析器将解析的逻辑视图名传给DispatcherServlet。
>
> DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
##### 2.2.1 XML代码:理解上面原理:
> web.xml
>
> ```xml
>
> 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">
>
>
>
> springmvc
> org.springframework.web.servlet.DispatcherServlet
>
>
> contextConfigLocation
> classpath:springmvc-servlet.xml
>
>
> 1
>
>
>
>
>
> springmvc
> /
>
>
> ```
>
> springmvc-servlet
>
> ```xml
>
> 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">
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> ```
>
> HelloController
>
> ```java
> import org.springframework.web.servlet.ModelAndView;
> import org.springframework.web.servlet.mvc.Controller;
>
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
> import org.springframework.web.servlet.mvc.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;
> }
> }
> ```
##### 2.2.2 注解版SpringMVC[重点]
注意:在视图解析器中我们把所以的视图都放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问
**步骤:**
1. 新建一个web项目
```xml
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc-servlet.xml
1
springmvc
/
```
2. 导入相关jar包
```xml
4.0.0
org.example
springMVC
pom
1.0-SNAPSHOT
//此处需注意
spring-01-servlet
spring-02-hellomvc
spring-02-hellomvc2
spring-03-annocation
junit
junit
4.13.2
test
org.springframework
spring-webmvc
5.3.12
javax.servlet
servlet-api
2.5
javax.servlet
jstl
1.2
src/main/resources
**/*.properties
**/*.xml
false
src/main/java
**/*.properties
**/*.xml
false
```
3. 编写web.xml,注册DispatcherServlet
4. 编写springmvc配置文件
```xml
```
5. 创建对应的控制类:controller
```java
package com.smile.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/hello")
public class HelloController {
//真实访问地址:项目名/HelloController/hello
@RequestMapping("/h1")
public String hello(Model model){
//封装数据:向模型中添加属性msg与值 可以在也页面使用
model.addAttribute("msg", "helloSpringMVC Annocation ok");
//web-inf/jsp/hello.jsp
return "hello"; //会被视图解析器处理
}
}
```
6. 完善前端视图和controller之间的对应
7. 测试运行调试
##### 使用springMVC必须配置的三大件:
**处理器映射器、处理器适配器、视图解析器**
在注解中我们只需要手动配置视图解析器,而处理器映射器和处理器适配器只需要开启注解取代即可。
### 3 RequetMapping
@RequestMapping:注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上,用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
### 4RestFul风格
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件更简洁,更有层次感,更易于实现缓存等机制。
```java
package com.smile.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
public class RestFulController {
//原来的 : http://localhost:8080/add?a=1&b=3
//RestFul: http://localhost:8080/add/a/b
//使用RestFul时,@PathVariable为请求参数 同时请求路径做修改,不同的请求方式Post或Get访问对应的,
// @RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.GET)
@GetMapping("/add/{a}/{b}")
public String test1(@PathVariable int a, @PathVariable int b, Model model){
int res = a+b;
model.addAttribute("msg","result is :"+res);
return "test1";
}
@PostMapping("/add/{a}/{b}")
public String test2(@PathVariable int a, @PathVariable int b, Model model){
int res = a+b;
model.addAttribute("msg","result2 is :"+res);
return "test1";
}
}
```
##### 组合注解:
> @GetMapping
>
> @PostMapping
>
> @DeleteMapping
>
> @PutMapping
>
> @PatchMapping
### 5 SpringMVC 数据处理
##### 5.1 重定向和转发
```java
//不需要视图解析器情况下:
@PostMapping("/m1/t1")
public String test3(Model model){
model.addAttribute("msg","result2 is :"+res);
//重定向:地址会改变
return "redirect:/test1.jsp";
//转发 :地址不会变
return "test1";
}
```
##### 5.2 后端数据处理
**1、提交的域名称和处理方法的参数名一致**
提交数据 : http://localhost:8080/hello?name=贾富荣
处理方法 :
```java
@RequestMapping("/hello")
public String hello(String name){
System.out.println(name); //贾富荣
return "hello";
}
```
**2、提交的域名称和处理方法的参数名不一致**
提交数据 : http://localhost:8080/hello?username=jia
处理方法 :
```java
//@RequestParam("username") : username提交的域的名称 .
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name){
System.out.println(name); //jia
return "hello";
}
```
**3、提交的是一个对象**
要求提交的表单域和对象的属性名一致 , 参数使用对象即可
1、实体类
```java
public class User {
private int id;
private String name;
private int age;
//构造
//get/set
//tostring()
}
```
2、提交数据 : http://localhost:8080/mvc04/user?name=jia&id=1&age=15
3、处理方法 :
- 接收前端用户传递的参数,判断参数的名字,假如名字直接在方法上,可直接使用
- 假设传递的参数是一个对象User。匹配User对象中的字段名:如果名字一致则ok,否则为null
```java
@RequestMapping("/user")
public String user(User user){
System.out.println(user);
return "hello";
}
```
后台输出 : User { id=1, name='jia', age=15 }
说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。
##### 5.3 数据显示到前端
**第一种 : 通过ModelAndView**
```java
public class ControllerTest1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//返回一个模型视图对象
ModelAndView mv = new ModelAndView();
mv.addObject("msg","ControllerTest1");
mv.setViewName("test");
return mv;
}
}
```
**第二种 : 通过ModelMap**
```java
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap model){
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
model.addAttribute("name",name);
System.out.println(name);
return "hello";
}
```
**第三种 : 通过Model**
```java
@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model){
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
model.addAttribute("msg",name);
System.out.println(name);
return "test";
}
```
> Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解;
>
> ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;
>
> ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。
### 6 乱码问题
1. Post请求乱码,Get请求正常
```java
@Controller
public class EncodingController {
//过滤器解决乱码
@GetMapping("/e/t")
//@PostMapping("/e/t") //使用Post请求乱码,get正常
public String test1(String name, Model model){
model.addAttribute("msg", name);
return "test1";
}
}
```
2. SpringMVC给我们提供了一个过滤器 , 可以在web.xml中配置 (判断是否已解决?)
```xml
encoding
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
encoding
/*
```
3. 修改tomcat配置文件:设置编码
server.xml:
```xml
```
4.终极 自定义过滤器
```java
package com.smile.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 {
public void destroy() {
}
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);
}
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 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 parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
if (values == null) {
return null;
}
return values[0]; // 取回参数的第一个值
}
//取所有值
@Override
public String[] getParameterValues(String name) {
Map parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
return values;
}
}
```
去web.xml配置
```xml
encoding
com.smile.filter.GenericEncodingFilter
encoding
/*
```
### 7JSON
json的全称为:JavaScript Object Notation,是一种轻量级的数据交互格式。
前端JavaScript自带JSON:
```html
```
##### 7.1 Jackson
##### 7.2 Fastjson
### 问题:
##### 1. 404错误:

查看是否存在lib包

解决方案:

##### 2.idea中lib导入失败
在pom.xml中添加如下代码:
```xml
src/main/resources
**/*.properties
**/*.xml
false
src/main/java
**/*.properties
**/*.xml
//注意
false
```