文章目录
- 三 SpringMvc
- 3.1 说说SpringMvc三层架构?
- 3.2 说说SpringMvc原理?
- 3.3 说说SpringMvc的常用注解?
- 3.4 谈谈转发与重定向?
- 3.5 怎样解决乱码问题?
- 3.6 过滤器与拦截器的区别?
三 SpringMvc
3.1 说说SpringMvc三层架构?
- MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。
- 是将业务逻辑、数据、显示分离的方法来组织代码。
- MVC主要作用是降低了视图与业务逻辑间的双向偶合。
- MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。
Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。
3.2 说说SpringMvc原理?
DispatcherServlet
表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet
接收请求并拦截请求。HandlerMapping
为处理器映射。DispatcherServlet
调用HandlerMapping,HandlerMapping
根据请求url查找Handler
。HandlerExecution
表示具体的Handler,其主要作用是根据url查找控制器HandlerExecution
将解析后的信息传递给DispatcherServlet
,如解析控制器映射等。HandlerAdapter
表示处理器适配器,其按照特定的规则去执行Handler。Handler
让具体的Controller
执行。Controller
将具体的执行信息返回给HandlerAdapter
,如ModelAndView。HandlerAdapter
将视图逻辑名或模型传递给DispatcherServlet
。DispatcherServlet
调用视图解析器(ViewResolver
)来解析HandlerAdapter
传递的逻辑视图名。- 视图解析器将解析的逻辑视图名传给
DispatcherServlet
。 DispatcherServlet
根据视图解析器解析的视图结果,调用具体的视图。- 最终视图呈现给用户。
我们来看一下吧:
3.3 说说SpringMvc的常用注解?
@RequestMapping
:用于处理请求 url 映射的注解。@RequestBody
:注解实现接收http请求的json数据,将json转换为java对象。@ResponseBody
:注解实现将conreoller方法返回对象转化为json对象响应给客户。@RestController
:@ResponseBody
+@Controller
。@Controller
: 用于标记在一个类上,使用它标记的类就是一个Spring MVC Controller
对象。@PathVariable
: 获取请求路径上的变量值。@RequestParam
:提交的域名称和处理方法的参数名不一致。
3.4 谈谈转发与重定向?
-
直接转发方式(Forward),客户端和浏览器只发出一次请求,Servlet、HTML、JSP或其它信息资源,由第二个信息资源响应该请求,在请求对象request中,保存的对象对于每个信息资源是共享的。(服务端)
-
间接转发方式(Redirect)实际是两次HTTP请求,服务器端在响应第一次请求的时候,让浏览器再向另外一个URL发出请求,从而达到转发的目的。(客服端)
-
举个通俗的例子:
直接转发就相当于:“A找B借钱,B说没有,B去找C借,借到借不到都会把消息传递给A”;
间接转发就相当于:“A找B借钱,B说没有,让A去找C借”。
-
(1)转发:在返回值前面加"
forward:
"。(2)重定向:在返回值前面加"
redirect:
"。
3.5 怎样解决乱码问题?
- 方法一
<!--过滤器问题-->
<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>
- 终极解决方法
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;
}
}
3.6 过滤器与拦截器的区别?
过滤器与拦截器的区别:拦截器是AOP思想的具体应用。
过滤器
servlet
规范中的一部分,任何java web
工程都可以使用- 在
url-pattern
中配置了/*
之后,可以对所有要访问的资源进行拦截
拦截器
- 拦截器是
SpringMVC
框架自己的,只有使用了SpringMVC
框架的工程才能使用 - 拦截器只会拦截访问的控制器方法, 如果访问的是
jsp/html/css/image/js
是不会进行拦截的
更多推荐
2021最详细面试题(八)SpringMvc
发布评论