springMvc源码刨析笔记
MVC 全名是 Model View Controller,是 模型(model)-视图(view)-控制器(controller) 的缩写, 是⼀种⽤于设计创建 Web 应⽤程序表现层的模式。
1.执行流程
2.九大组件
//文件上传组件
initMultipartResolver(context);
//初始化本地语言环境
initLocaleResolver(context);
//初始化模板处理器
initThemeResolver(context);
//初始化HandleMapping
initHandlerMappings(context);
//初始化参数适配器
initHandlerAdapters(context);
//初始化异常拦截器
initHandlerExceptionResolvers(context);
//初始化试视图预处理器
initRequestToViewNameTranslator(context);
//试图转换器
initViewResolvers(context);
//falshMap管理器
initFlashMapManager(context);
2.自定义springMvc框架
1.声明创建(LgDispatcherServlet)并继承Servlet
springmvc.properties
scanPackage=com.lagou.demo
LgDispatcherServlet 实现了servlet对象的init() doGet() doPost()方法
public class LgDispatcherServlet extends HttpServlet {
@Override
public void init(ServletConfig config
) throws ServletException
{
}
@Override
protected void doGet(HttpServletRequest req
, HttpServletResponse resp
) throws ServletException
, IOException
{
doPost(req
,resp
);
}
@Override
protected void doPost(HttpServletRequest req
, HttpServletResponse resp
) throws ServletException
, IOException
{
}
}
2.声明注解
LagouAutowired,LagouController,LagouRequestMapping,LagouService
@Documented
@Target(ElementType
.FIELD
)
@Retention(RetentionPolicy
.RUNTIME
)
public @
interface LagouAutowired {
String
value() default "";
}
3.加载配置文件
private Properties properties
= new Properties();
String contextConfigLocation
= config
.getInitParameter("contextConfigLocation");
doLoadConfig(contextConfigLocation
);
private void doLoadConfig(String contextConfigLocation
) {
InputStream resourceAsStream
= this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation
);
try {
properties
.load(resourceAsStream
);
} catch (IOException e
) {
e
.printStackTrace();
}
}
4.扫描包
private List
<String> classNames
= new ArrayList<>();
doScan(properties
.getProperty("scanPackage"));
private void doScan(String scanPackage
) {
String scanPackagePath
= Thread
.currentThread().getContextClassLoader().getResource("").getPath() + scanPackage
.replaceAll("\\.", "/");
File pack
= new File(scanPackagePath
);
File
[] files
= pack
.listFiles();
for(File file
: files
) {
if(file
.isDirectory()) {
doScan(scanPackage
+ "." + file
.getName());
}else if(file
.getName().endsWith(".class")) {
String className
= scanPackage
+ "." + file
.getName().replaceAll(".class", "");
classNames
.add(className
);
}
}
}
5.初始化对象
private void doInstance() {
if(classNames
.size() == 0) return;
try{
for (int i
= 0; i
< classNames
.size(); i
++) {
String className
= classNames
.get(i
);
Class
<?> aClass
= Class
.forName(className
);
if(aClass
.isAnnotationPresent(LagouController
.class)) {
String simpleName
= aClass
.getSimpleName();
String lowerFirstSimpleName
= lowerFirst(simpleName
);
Object o
= aClass
.newInstance();
ioc
.put(lowerFirstSimpleName
,o
);
}else if(aClass
.isAnnotationPresent(LagouService
.class)) {
LagouService annotation
= aClass
.getAnnotation(LagouService
.class);
String beanName
= annotation
.value();
if(!"".equals(beanName
.trim())) {
ioc
.put(beanName
,aClass
.newInstance());
}else{
beanName
= lowerFirst(aClass
.getSimpleName());
ioc
.put(beanName
,aClass
.newInstance());
}
Class
<?>[] interfaces
= aClass
.getInterfaces();
for (int j
= 0; j
< interfaces
.length
; j
++) {
Class
<?> anInterface
= interfaces
[j
];
ioc
.put(anInterface
.getName(),aClass
.newInstance());
}
}else{
continue;
}
}
}catch (Exception e
) {
e
.printStackTrace();
}
}
public String
lowerFirst(String str
) {
char[] chars
= str
.toCharArray();
if('A' <= chars
[0] && chars
[0] <= 'Z') {
chars
[0] += 32;
}
return String
.valueOf(chars
);
}
6.实例化对象(AutoWired)
doAutoWired();
private void doAutoWired() {
if(ioc
.isEmpty()) {return;}
for(Map
.Entry
<String,Object> entry
: ioc
.entrySet()) {
Field
[] declaredFields
= entry
.getValue().getClass().getDeclaredFields();
for (int i
= 0; i
< declaredFields
.length
; i
++) {
Field declaredField
= declaredFields
[i
];
if(!declaredField
.isAnnotationPresent(LagouAutowired
.class)) {
continue;
}
LagouAutowired annotation
= declaredField
.getAnnotation(LagouAutowired
.class);
String beanName
= annotation
.value();
if("".equals(beanName
.trim())) {
beanName
= declaredField
.getType().getName();
}
declaredField
.setAccessible(true);
try {
declaredField
.set(entry
.getValue(),ioc
.get(beanName
));
} catch (IllegalAccessException e
) {
e
.printStackTrace();
}
}
}
}
7.HandlerMapping处理器映射器(url与method)
private List
<Handler> handlerMapping
= new ArrayList<>();
===============================================================
private void initHandlerMapping() {
if(ioc
.isEmpty()) {return;}
for(Map
.Entry
<String,Object> entry
: ioc
.entrySet()) {
Class
<?> aClass
= entry
.getValue().getClass();
if(!aClass
.isAnnotationPresent(LagouController
.class)) {continue;}
String baseUrl
= "";
if(aClass
.isAnnotationPresent(LagouRequestMapping
.class)) {
LagouRequestMapping annotation
= aClass
.getAnnotation(LagouRequestMapping
.class);
baseUrl
= annotation
.value();
}
Method
[] methods
= aClass
.getMethods();
for (int i
= 0; i
< methods
.length
; i
++) {
Method method
= methods
[i
];
if(!method
.isAnnotationPresent(LagouRequestMapping
.class)) {continue;}
LagouRequestMapping annotation
= method
.getAnnotation(LagouRequestMapping
.class);
String methodUrl
= annotation
.value();
String url
= baseUrl
+ methodUrl
;
Handler handler
= new Handler(entry
.getValue(),method
, Pattern
.compile(url
));
Parameter
[] parameters
= method
.getParameters();
for (int j
= 0; j
< parameters
.length
; j
++) {
Parameter parameter
= parameters
[j
];
if(parameter
.getType() == HttpServletRequest
.class || parameter
.getType() == HttpServletResponse
.class) {
handler
.getParamIndexMapping().put(parameter
.getType().getSimpleName(),j
);
}else{
handler
.getParamIndexMapping().put(parameter
.getName(),j
);
}
}
handlerMapping
.add(handler
);
}
}
}
public class Handler {
private Object controller
;
private Method method
;
private Pattern pattern
;
private Map
<String,Integer> paramIndexMapping
;
}
8.post请求参数处理
@Override
protected void doPost(HttpServletRequest req
, HttpServletResponse resp
) throws ServletException
, IOException
{
Handler handler
= getHandler(req
);
if(handler
== null
) {
resp
.getWriter().write("404 not found");
return;
}
Class
<?>[] parameterTypes
= handler
.getMethod().getParameterTypes();
Object
[] paraValues
= new Object[parameterTypes
.length
];
Map
<String
, String
[]> parameterMap
= req
.getParameterMap();
for(Map
.Entry
<String
,String
[]> param
: parameterMap
.entrySet()) {
String value
= StringUtils
.join(param
.getValue(), ",");
if(!handler
.getParamIndexMapping().containsKey(param
.getKey())) {continue;}
Integer index
= handler
.getParamIndexMapping().get(param
.getKey());
paraValues
[index
] = value
;
}
int requestIndex
= handler
.getParamIndexMapping().get(HttpServletRequest
.class.getSimpleName());
paraValues
[requestIndex
] = req
;
int responseIndex
= handler
.getParamIndexMapping().get(HttpServletResponse
.class.getSimpleName());
paraValues
[responseIndex
] = resp
;
try {
handler
.getMethod().invoke(handler
.getController(),paraValues
);
} catch (IllegalAccessException e
) {
e
.printStackTrace();
} catch (InvocationTargetException e
) {
e
.printStackTrace();
}
}
private Handler
getHandler(HttpServletRequest req
) {
if(handlerMapping
.isEmpty()){return null
;}
String url
= req
.getRequestURI();
for(Handler handler
: handlerMapping
) {
Matcher matcher
= handler
.getPattern().matcher(url
);
if(!matcher
.matches()){continue;}
return handler
;
}
return null
;
}
9.加入到web.xml
<servlet>
<servlet-name>lgoumvc
</servlet-name>
<servlet-class>com.lagou.edu.mvcframework.servlet.LgDispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation
</param-name>
<param-value>springmvc.properties
</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>lgoumvc
</servlet-name>
<url-pattern>/*
</url-pattern>
</servlet-mapping>
自定义答案的核心类(LgDispatcherServlet)
package com
.lagou
.edu
.mvcframework
.servlet
;
import com
.lagou
.demo
.service
.IDemoService
;
import com
.lagou
.edu
.mvcframework
.annotations
.*
;
import com
.lagou
.edu
.mvcframework
.pojo
.Handler
;
import org
.apache
.commons
.lang3
.StringUtils
;
import javax
.servlet
.ServletConfig
;
import javax
.servlet
.ServletException
;
import javax
.servlet
.http
.HttpServlet
;
import javax
.servlet
.http
.HttpServletRequest
;
import javax
.servlet
.http
.HttpServletResponse
;
import java
.io
.File
;
import java
.io
.IOException
;
import java
.io
.InputStream
;
import java
.lang
.reflect
.Field
;
import java
.lang
.reflect
.InvocationTargetException
;
import java
.lang
.reflect
.Method
;
import java
.lang
.reflect
.Parameter
;
import java
.util
.*
;
import java
.util
.regex
.Matcher
;
import java
.util
.regex
.Pattern
;
public class LgDispatcherServlet extends HttpServlet {
private Properties properties
= new Properties();
private List
<String> classNames
= new ArrayList<>();
private Map
<String,Object> ioc
= new HashMap<String,Object>();
private Map
<Handler
,List
<String>> securityMap
= new HashMap<>();
private List
<Handler> handlerMapping
= new ArrayList<>();
@Override
public void init(ServletConfig config
) throws ServletException
{
String contextConfigLocation
= config
.getInitParameter("contextConfigLocation");
doLoadConfig(contextConfigLocation
);
doScan(properties
.getProperty("scanPackage"));
doInstance();
doAutoWired();
initHandlerMapping();
System
.out
.println("lagou mvc 初始化完成....");
}
private void initHandlerMapping() {
if(ioc
.isEmpty()) {return;}
for(Map
.Entry
<String,Object> entry
: ioc
.entrySet()) {
Class
<?> aClass
= entry
.getValue().getClass();
if(!aClass
.isAnnotationPresent(LagouController
.class)) {continue;}
String baseUrl
= "";
if(aClass
.isAnnotationPresent(LagouRequestMapping
.class)) {
LagouRequestMapping annotation
= aClass
.getAnnotation(LagouRequestMapping
.class);
baseUrl
= annotation
.value();
}
Method
[] methods
= aClass
.getMethods();
for (int i
= 0; i
< methods
.length
; i
++) {
Method method
= methods
[i
];
if(!method
.isAnnotationPresent(LagouRequestMapping
.class)) {continue;}
LagouRequestMapping annotation
= method
.getAnnotation(LagouRequestMapping
.class);
String methodUrl
= annotation
.value();
String url
= baseUrl
+ methodUrl
;
Handler handler
= new Handler(entry
.getValue(),method
, Pattern
.compile(url
));
Parameter
[] parameters
= method
.getParameters();
for (int j
= 0; j
< parameters
.length
; j
++) {
Parameter parameter
= parameters
[j
];
if(parameter
.getType() == HttpServletRequest
.class || parameter
.getType() == HttpServletResponse
.class) {
handler
.getParamIndexMapping().put(parameter
.getType().getSimpleName(),j
);
}else{
handler
.getParamIndexMapping().put(parameter
.getName(),j
);
}
}
if(aClass
.isAnnotationPresent(Security
.class) && method
.isAnnotationPresent(Security
.class)) {
Security controllerSecurity
= aClass
.getAnnotation(Security
.class);
String
[] controllerUsernames
= controllerSecurity
.value();
List
<String> controllerUnameList
= Arrays
.asList(controllerUsernames
);
Security handlerSecurity
= method
.getAnnotation(Security
.class);
String
[] handlerUsernames
= handlerSecurity
.value();
List
<String> handlerUnameList
= Arrays
.asList(handlerUsernames
);
controllerUnameList
= new ArrayList<>(controllerUnameList
);
handlerUnameList
= new ArrayList<>(handlerUnameList
);
controllerUnameList
.retainAll(handlerUnameList
);
securityMap
.put( handler
, controllerUnameList
);
}else if(aClass
.isAnnotationPresent(Security
.class)) {
Security controllerSecurity
= aClass
.getAnnotation(Security
.class);
String
[] controllerUsernames
= controllerSecurity
.value();
List
<String> controllerUnameList
= Arrays
.asList(controllerUsernames
);
securityMap
.put( handler
, controllerUnameList
);
}else if(method
.isAnnotationPresent(Security
.class)) {
Security handlerSecurity
= method
.getAnnotation(Security
.class);
String
[] handlerUsernames
= handlerSecurity
.value();
List
<String> handlerUnameList
= Arrays
.asList(handlerUsernames
);
securityMap
.put( handler
, handlerUnameList
);
}
handlerMapping
.add(handler
);
}
}
}
private void doAutoWired() {
if(ioc
.isEmpty()) {return;}
for(Map
.Entry
<String,Object> entry
: ioc
.entrySet()) {
Field
[] declaredFields
= entry
.getValue().getClass().getDeclaredFields();
for (int i
= 0; i
< declaredFields
.length
; i
++) {
Field declaredField
= declaredFields
[i
];
if(!declaredField
.isAnnotationPresent(LagouAutowired
.class)) {
continue;
}
LagouAutowired annotation
= declaredField
.getAnnotation(LagouAutowired
.class);
String beanName
= annotation
.value();
if("".equals(beanName
.trim())) {
beanName
= declaredField
.getType().getName();
}
declaredField
.setAccessible(true);
try {
declaredField
.set(entry
.getValue(),ioc
.get(beanName
));
} catch (IllegalAccessException e
) {
e
.printStackTrace();
}
}
}
}
private void doInstance() {
if(classNames
.size() == 0) return;
try{
for (int i
= 0; i
< classNames
.size(); i
++) {
String className
= classNames
.get(i
);
Class
<?> aClass
= Class
.forName(className
);
if(aClass
.isAnnotationPresent(LagouController
.class)) {
String simpleName
= aClass
.getSimpleName();
String lowerFirstSimpleName
= lowerFirst(simpleName
);
Object o
= aClass
.newInstance();
ioc
.put(lowerFirstSimpleName
,o
);
}else if(aClass
.isAnnotationPresent(LagouService
.class)) {
LagouService annotation
= aClass
.getAnnotation(LagouService
.class);
String beanName
= annotation
.value();
if(!"".equals(beanName
.trim())) {
ioc
.put(beanName
,aClass
.newInstance());
}else{
beanName
= lowerFirst(aClass
.getSimpleName());
ioc
.put(beanName
,aClass
.newInstance());
}
Class
<?>[] interfaces
= aClass
.getInterfaces();
for (int j
= 0; j
< interfaces
.length
; j
++) {
Class
<?> anInterface
= interfaces
[j
];
ioc
.put(anInterface
.getName(),aClass
.newInstance());
}
}else{
continue;
}
}
}catch (Exception e
) {
e
.printStackTrace();
}
}
public String
lowerFirst(String str
) {
char[] chars
= str
.toCharArray();
if('A' <= chars
[0] && chars
[0] <= 'Z') {
chars
[0] += 32;
}
return String
.valueOf(chars
);
}
private void doScan(String scanPackage
) {
String scanPackagePath
= Thread
.currentThread().getContextClassLoader().getResource("").getPath() + scanPackage
.replaceAll("\\.", "/");
File pack
= new File(scanPackagePath
);
File
[] files
= pack
.listFiles();
for(File file
: files
) {
if(file
.isDirectory()) {
doScan(scanPackage
+ "." + file
.getName());
}else if(file
.getName().endsWith(".class")) {
String className
= scanPackage
+ "." + file
.getName().replaceAll(".class", "");
classNames
.add(className
);
}
}
}
private void doLoadConfig(String contextConfigLocation
) {
InputStream resourceAsStream
= this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation
);
try {
properties
.load(resourceAsStream
);
} catch (IOException e
) {
e
.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest req
, HttpServletResponse resp
) throws ServletException
, IOException
{
doPost(req
,resp
);
}
@Override
protected void doPost(HttpServletRequest req
, HttpServletResponse resp
) throws ServletException
, IOException
{
Handler handler
= getHandler(req
);
if(handler
== null
) {
resp
.getWriter().write("404 not found");
return;
}
List
<String> usernameList
= securityMap
.get(handler
);
if(usernameList
!= null
&& !usernameList
.contains(req
.getParameter("username"))) {
resp
.getWriter().write("sorry,the request has been forbidden---security");
return;
}
Class
<?>[] parameterTypes
= handler
.getMethod().getParameterTypes();
Object
[] paraValues
= new Object[parameterTypes
.length
];
Map
<String
, String
[]> parameterMap
= req
.getParameterMap();
for(Map
.Entry
<String
,String
[]> param
: parameterMap
.entrySet()) {
String value
= StringUtils
.join(param
.getValue(), ",");
if(!handler
.getParamIndexMapping().containsKey(param
.getKey())) {continue;}
Integer index
= handler
.getParamIndexMapping().get(param
.getKey());
paraValues
[index
] = value
;
}
int requestIndex
= handler
.getParamIndexMapping().get(HttpServletRequest
.class.getSimpleName());
paraValues
[requestIndex
] = req
;
int responseIndex
= handler
.getParamIndexMapping().get(HttpServletResponse
.class.getSimpleName());
paraValues
[responseIndex
] = resp
;
try {
handler
.getMethod().invoke(handler
.getController(),paraValues
);
} catch (IllegalAccessException e
) {
e
.printStackTrace();
} catch (InvocationTargetException e
) {
e
.printStackTrace();
}
}
private Handler
getHandler(HttpServletRequest req
) {
if(handlerMapping
.isEmpty()){return null
;}
String url
= req
.getRequestURI();
for(Handler handler
: handlerMapping
) {
Matcher matcher
= handler
.getPattern().matcher(url
);
if(!matcher
.matches()){continue;}
return handler
;
}
return null
;
}
}
3.源码刨析
1.getHandler()
protected HandlerExecutionChain
getHandler(HttpServletRequest request
) throws Exception
{
if (this.handlerMappings
!= null
) {
for (HandlerMapping mapping
: this.handlerMappings
) {
HandlerExecutionChain handler
= mapping
.getHandler(request
);
if (handler
!= null
) {
return handler
;
}
}
}
return null
;
}
2.getHandlerAdapter()
protected HandlerAdapter
getHandlerAdapter(Object handler
) throws ServletException
{
if (this.handlerAdapters
!= null
) {
for (HandlerAdapter adapter
: this.handlerAdapters
) {
if (adapter
.supports(handler
)) {
return adapter
;
}
}
}
}
3.handle()
public void invokeAndHandle(ServletWebRequest webRequest
, ModelAndViewContainer mavContainer
,
Object
... providedArgs
) throws Exception
{
Object returnValue
= invokeForRequest(webRequest
, mavContainer
, providedArgs
);
setResponseStatus(webRequest
);
}
public Object
invokeForRequest(NativeWebRequest request
, @Nullable ModelAndViewContainer mavContainer
,
Object
... providedArgs
) throws Exception
{
Object
[] args
= getMethodArgumentValues(request
, mavContainer
, providedArgs
);
return doInvoke(args
);
}
protected Object
[] getMethodArgumentValues(NativeWebRequest request
, @Nullable ModelAndViewContainer mavContainer
,
Object
... providedArgs
) throws Exception
{
MethodParameter
[] parameters
= getMethodParameters();
if (ObjectUtils
.isEmpty(parameters
)) {
return EMPTY_ARGS
;
}
Object
[] args
= new Object[parameters
.length
];
for (int i
= 0; i
< parameters
.length
; i
++) {
MethodParameter parameter
= parameters
[i
];
parameter
.initParameterNameDiscovery(this.parameterNameDiscoverer
);
args
[i
] = findProvidedArgument(parameter
, providedArgs
);
args
[i
] = this.resolvers
.resolveArgument(parameter
, mavContainer
, request
, this.dataBinderFactory
);
return args
;
}
4.processDispatchResult()
processDispatchResult(processedRequest
, response
, mappedHandler
, mv
, dispatchException
);
private void processDispatchResult()
{
if (mv
!= null
&& !mv
.wasCleared()) {
render(mv
, request
, response
);
if (errorView
) {
WebUtils
.clearErrorRequestAttributes(request
);
}
}
if (mappedHandler
!= null
) {
mappedHandler
.triggerAfterCompletion(request
, response
, null
);
}
}
protected void render(ModelAndView mv
, HttpServletRequest request
, HttpServletResponse response
) throws Exception
{
view
= resolveViewName(viewName
, mv
.getModelInternal(), locale
, request
);
}
public View
resolveViewName(String viewName
, Locale locale
) throws Exception
{
if (view
== null
) {
synchronized (this.viewCreationCache
) {
view
= this.viewCreationCache
.get(cacheKey
);
if (view
== null
) {
view
= createView(viewName
, locale
);
if (view
== null
&& this.cacheUnresolved
) {
view
= UNRESOLVED_VIEW
;
}
if (view
!= null
) {
this.viewAccessCache
.put(cacheKey
, view
);
this.viewCreationCache
.put(cacheKey
, view
);
}
}
}
}
return (view
!= UNRESOLVED_VIEW
? view
: null
);
}
}
4.什么是 RESTful
REST(英⽂:Representational State Transfer,简称 REST)描述了⼀个架构样式的⽹络系统,
1.RESTfu有哪些l区别
原有的url设计http://localhost:8080/user/queryUserById.action?id=3 restful设计 http://localhost:8080/user/3 常规操作就是增删改查 根据请求⽅式不同,代表要做不同的操作 get 查询,获取资源 /account/1 HTTP GET :得到 id = 1 的 account post 增加,新建资源 put 更新 /account/1 HTTP PUT:更新 id = 1 的 account delete 删除资源 /account/1 HTTP DELETE:删除 id = 1 的 account
<form method="post" action="/demo/handle">
<input type="text" name="username"/>
<input type="submit" value="提交rest_post请求"/>
</form>
<form method="post" action="/demo/handle/15/lisi">
<input type="hidden" name="_method" value="put"/>
<input type="submit" value="提交rest_put请求"/>
</form>
@RequestMapping(value
= "/handle/{id}/{name}",method
= {RequestMethod
.PUT
})
public ModelAndView
handlePut(@PathVariable("id") Integer
id
,@PathVariable("name") String username
) {
Date date
= new Date();
ModelAndView modelAndView
= new ModelAndView();
modelAndView
.addObject("date",date
);
modelAndView
.setViewName("success");
return modelAndView
;
}
<filter>
<filter-name>hiddenHttpMethodFilter
</filter-name>
<filterclass>org.springframework.web.filter.HiddenHttpMethodFilter
</filterclass>
</filter>
<filter-mapping>
<filter-name>encoding
</filter-name>
<url-pattern>/*
</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter
</filter-name>
<url-pattern>/*
</url-pattern>
</filter-mapping>
5.自定义拦截器
1.接口实现HandlerInterceptor
public class MyIntercepter01 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request
, HttpServletResponse
response
, Object handler
) throws Exception
{
System
.out
.println("MyIntercepter01 preHandle......");
return true;
}
@Override
public void postHandle(HttpServletRequest request
, HttpServletResponse
response
, Object handler
, ModelAndView modelAndView
) throws Exception
{
System
.out
.println("MyIntercepter01 postHandle......");
}
@Override
public void afterCompletion(HttpServletRequest request
,
HttpServletResponse response
, Object handler
, Exception ex
) throws Exception
{
System
.out
.println("MyIntercepter01 afterCompletion......");
}
}
2.注册SpringMVC拦截器
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.lagou.edu.interceptor.MyIntercepter01"/>
</mvc:interceptor>
</mvc:interceptors>
6.整合SSM
数据库连接池以及事务管理都交给Spring容器来完成
SqlSessionFactory对象应该放到Spring容器中作为单例对象管理
Mapper动态代理对象交给Spring管理,我们从Spring容器中直接获得Mapper的代理对象
6.1web.xml
<context-param>
<param-name>contextConfigLocation
</param-name>
<param-value>classpath*:applicationContext*.xml
</param-value>
</context-param>
<listener>
<listenerclass>org.springframework.web.context.ContextLoaderListener
</listenerclass>
</listener>
<servlet>
<servlet-name>springmvc
</servlet-name>
<servletclass>org.springframework.web.servlet.DispatcherServlet
</servletclass>
<init-param>
<param-name>contextConfigLocation
</param-name>
<param-value>classpath*:springmvc.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
6.2整合springMvc(springmvc.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/springcontext.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<context:component-scan base-package="com.lagou.edu.controller"/>
<mvc:annotation-driven/>
</beans>
6.3整合Dao(applicationContext-dao.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">
<context:component-scan base-package="com.lagou.edu.mapper"/>
<context:property-placeholderlocation="classpath:jdbc.properties"/>
<bean id="dataSource"
class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="typeAliasesPackage" value="com.lagou.edu.pojo"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.lagou.edu.mapper"/>
<property name="sqlSessionFactoryBeanName"
value="sqlSessionFactory"/>
</bean>
</beans>
6.4applicationContext-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:lgContext="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">
<lgContext:component-scan base-package="com.lagou.edu.service"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
7.设计模式
1.策略模式
策略模式(Strategy),就是⼀个问题有多种解决⽅案,选择其中的⼀种使⽤,这种情况下我们使⽤策略模式来实现灵活地选择,也能够⽅便地增加新的解决⽅。⽐如做数学题,⼀个问题的解法可能有多种;再⽐如商场的打折促销活动,打折⽅案也有很多种,有些商品是不参与折扣活动要按照原价销售,有些商品打8.5折,有些打6折,有些是返现5元等
public abstract class AbstractDiscount {
protected double finalPrice
;
protected String desc
;
public AbstractDiscount(String desc
) {
this.desc
= desc
;
}
public abstract double discount(double price
);
}
public class Discount6 extends AbstractDiscount {
public Discount6() {
super("该商品可享受6折优惠");
}
@Override
public double discount(double price
) {
finalPrice
= price
* 0.6;
return finalPrice
;
}
}
public class BuyGoods {
private String goods
;
private double price
;
private AbstractDiscount abstractDiscount
;
public BuyGoods(String goods
, double price
, AbstractDiscount
abstractDiscount
) {
this.goods
= goods
;
this.price
= price
;
this.abstractDiscount
= abstractDiscount
;
}
public double calculate() {
double finalPrice
= abstractDiscount
.discount(this.price
);
String desc
= abstractDiscount
.getDesc();
System
.out
.println(MessageFormat
.format("商品:{0},原价:{1},{2},最终价格为:{3}", goods
, price
, desc
, finalPrice
));
return finalPrice
;
}
}
public static void main(String
[] args
) {
BuyGoods buyGoods1
= new BuyGoods("Java编程思想", 99.00, new
Discount85());
buyGoods1
.calculate();
BuyGoods buyGoods2
= new BuyGoods("罗技⿏标", 66, new Discount6());
buyGoods2
.calculate();
}
2.模板方法
模板⽅法模式是指定义⼀个算法的⻣架,并允许⼦类为⼀个或者多个步骤提供实现。模板⽅法模式使得⼦类可以在不改变算法结构的情况下,重新定义算法的某些步骤,属于⾏为型设计模式。采⽤模板⽅法模式的核⼼思路是处理某个流程的代码已经具备,但其中某些节点的代码暂时不能确定。此时可以使⽤模板⽅法。
public abstract class Interview {
private final void register() {
System
.out
.println("⾯试登记");
}
protected abstract void communicate();
private final void notifyResult() {
System
.out
.println("HR⼩姐姐通知⾯试结果");
}
protected final void process() {
this.register();
this.communicate();
this.notifyResult();
}
}
public class Interviewee1 extends Interview{
public void communicate() {
System
.out
.println("我是⾯试⼈员1,来⾯试Java⼯程师,我们聊的是Java相关内容");
}
}
public static void main(String
[] args
) {
Interview interviewee1
= new Interviewee1();
interviewee1
.process();
}
3.适配器模式
使得原本由于接⼝不兼容⽽不能⼀起⼯作、不能统⼀管理的那些类可以⼀起⼯作、可以进⾏统⼀管理解决接⼝不兼容⽽不能⼀起⼯作问题,
看下⾯⼀个⾮常经典的案例
在中国,⺠⽤电都是220v交流电,但是⼿机锂电池⽤的都是5v直流电。因此,我们给⼿机充电时就需要使⽤电源适配器来进⾏转换。使⽤代码还原这个⽣活场景
public class AC220 {
public int outputAC220V() {
int output
= 220;
System
.out
.println("输出交流电" + output
+ "V");
return output
;
}
}
public interface DC5 {
int outputDC5V();
}
public class PowerAdapter implements DC5 {
private AC220 ac220
;
public PowerAdapter(AC220 ac220
) {
this.ac220
= ac220
;
}
public int outputDC5V() {
int adapterInput
= ac220
.outputAC220V();
int adapterOutput
= adapterInput
/ 44;
System
.out
.println("使⽤ PowerAdapter 输⼊AC:" + adapterInput
+ "V 输出DC:" + adapterOutput
+ "V");
return adapterOutput
;
}
}
public static void main(String
[] args
) {
DC5 dc5
= new PowerAdapter(new AC220());
dc5
.outputDC5V();
}
问题
1.拦截器,监听器,过滤器
过滤器(Filter):在web.xml中配置 用来配置Post请求的编码过滤器
对Request请求起到过滤的作用,如果配置为/ 可以对所有的资源访问进行过滤
<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>
监听器(Listener):实现了javax.servlet.ServletContextListener 接⼝的服务器端组件,它随
Web应⽤的启动⽽启动,只初始化⼀次,然后会⼀直运⾏监视,随Web应⽤的停⽌⽽销毁
作⽤⼀:做⼀些初始化⼯作,web应⽤中spring容器启动ContextLoaderListener
作⽤⼆:监听web中的特定事件,⽐如HttpSession,ServletRequest的创建和销毁;变量的创建、
销毁和修改等。可以在某些动作前后增加处理,实现监控,⽐如统计在线⼈数,利⽤
HttpSessionLisener等。
public class MyHttpSessionListener implements HttpSessionListener {
public static int online
= 0;
@Override
public void sessionCreated(HttpSessionEvent se
) {
System
.out
.println("创建session");
online
++;
}
@Override
public void sessionDestroyed(HttpSessionEvent se
) {
System
.out
.println("销毁session");
}
}
@RequestMapping("/online")
@ResponseBody
public Object
online() {
return "当前在线人数:" + MyHttpSessionListener
.online
+ "人";
}
<context-param>
<param-name>contextConfigLocation
</param-name>
<param-value>classpath:spring/application*.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
拦截器(Interceptor):是SpringMVC、Struts等表现层框架⾃⼰的,不会拦截jsp/html/css/image的访问等,只会拦截访问的控制器⽅法(Handler)。
public class MyIntercepter01 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request
, HttpServletResponse
response
, Object handler
) throws Exception
{
System
.out
.println("MyIntercepter01 preHandle......");
return true;
}
@Override
public void postHandle(HttpServletRequest request
, HttpServletResponse
response
, Object handler
, ModelAndView modelAndView
) throws Exception
{
System
.out
.println("MyIntercepter01 postHandle......");
}
@Override
public void afterCompletion(HttpServletRequest request
,
HttpServletResponse response
, Object handler
, Exception ex
) throws Exception
{
System
.out
.println("MyIntercepter01 afterCompletion......");
}
}
注册SpringMvc拦截器
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.lagou.edu.interceptor.MyIntercepter01"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.lagou.edu.interceptor.MyIntercepter02"/>
</mvc:interceptor>
</mvc:interceptors>
配置的角度
从配置的⻆度也能够总结发现:serlvet、fifilter、listener是配置在web.xml中的,⽽interceptor是配置在表现层框架⾃⼰的配置⽂件中的
2.Pattern和Matcher用法
Pattern pattern
= Pattern
.compile("Java");
String test
="123Java456Java789Java";
String
[] result
= pattern
.split(test
);
for(String s
: result
)
System
.out
.println(s
);
}
Pattern类也自带一个静态匹配方法matches(String regex, CharSequence input),但只能进行全字符串匹配并且只能返回是否匹配上的boolean值
String test1
= "Java";
String test2
= "Java123456";
System
.out
.println(Pattern
.matches("Java",test1
));
System
.out
.println(Pattern
.matches("Java",test2
));
3.乱码问题解决
###3.1 Post乱码 Post请求乱码,web.xml中加⼊过滤器
<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>
<init-param>
<param-name>forceEncoding
</param-name>
<param-value>true
</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding
</filter-name>
<url-pattern>/*
</url-pattern>
</filter-mapping>
3.2get乱码
Get请求乱码(Get请求乱码需要修改tomcat下server.xml的配置)
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080"
protocol="HTTP/1.1" redirectPort="8443"/>
4.自定义框架式 参数是arg2
在web.xml中配置参数
<plugin>
<groupId>org.apache.maven.plugins
</groupId>
<artifactId>maven-compiler-plugin
</artifactId>
<version>3.1
</version>
<configuration>
<source>8
</source>
<target>8
</target>
<encoding>utf-8
</encoding>
<compilerArgs>
<arg>-parameters
</arg>
</compilerArgs>
</configuration>
</plugin>
单词
Flash 闪光 retrieve检索 specific特殊的,具体的 delegates 代表 Determine 确定决定 Modified 修改 process 进程,流程 theme 主题 previous 以前 Internal 内部 discoverer 发现 Destruction 破坏 Discovery发现 Provided提供,假如 》findProvidedArgument resolve 解析,决心》resolveArgument