在手写最基础的V1版本Spring之后,再次学习Spring中的核心源码,提取出Spring中核心的IoC、DI、MVC、AOP各组件的的分工,自己用代码手写完成这些组件。
1.调用Servlet init()方法,创建ApplicationContext
2.读取配置文件(peoperties、xml、yml)
3.BeanDefinitionReader解析配置文件,扫描相关的类,封装成BeanDefinition保存到了内存中
4.在ApplicationContext.getBean后,初始化IOC容器,并且实例化对象,封装成BeanWrapper。
5.完成DI注入
1.初始化九大组件之HandlerMapping:读取所有的RequestMapping中的url结合instance、Method缓存到HandlerMapping
2.初始化九大组件之HandlerAdapter:为每个HandlerMapping创建一个HandlerAdapter(目前其实没有适配改变内容)并缓存
3.初始化九大组件之ViewResolver:读取配置文件的模板根目录。
1.在IoC初始化所有类时,创建GPAdvisedSupport,读取AopConfig配置文件。
2.GPAdvisedSupport中解析配置文件,使用正则匹配,创建method - Advices对应缓存。
3.,匹配aop类,创建Proxy类替代原类初始化,在Proxy类中,读取method - Advices缓存,调用对应的advice方法。
源码实现部分由于在编写代码时,可能在同一个类中不断新增一些代码,所以并不是以编写顺序排序。
为了解析方便,我们用application.properties来代替application.xml文 件 ,具体配置内容如下:
#托管的类扫描包路径#
scanPackage=com.gupaoedu.vip.demo
templateRoot=layouts
#切面表达式expression#
pointCut=public .* com.gupaoedu.vip.demo.service..*Service..*(.*)
#切面类
aspectClass=com.gupaoedu.vip.demo.aspect.LogAspect
#前置通知回调方法
aspectBefore=before
#后置通知回调方法
aspectAfter=after
#异常通知回调方法
aspectAfterThrow=afterThrowing
#异常类型捕获
aspectAfterThrowingName=java.lang.Exception
大家都知道,所有依赖于web容器的项目,都是从读取web.xml文件开始的。我们先配置好web.xml
中的内容。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>Gupao Web Application</display-name>
<servlet>
<servlet-name>gpmvc</servlet-name>
<servlet-class>com.gupaoedu.vip.spring.framework.webmvc.servlet.GPDispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>application.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>gpmvc</servlet-name>
<url-pattern>/*
其中GPDispatcherServlet是有自己模拟Spring实现的核心功能类。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GPService {
String value() default "";
}
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GPAutowired {
String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GPController {
String value() default "";
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GPRequestMapping {
String value() default "";
}
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GPRequestParam {
String value() default "";
}
public class GPBeanDefinition {
private String factoryBeanName;
private String beanClassName;
public String getFactoryBeanName() {
return factoryBeanName;
}
public void setFactoryBeanName(String factoryBeanName) {
this.factoryBeanName = factoryBeanName;
}
public String getBeanClassName() {
return beanClassName;
}
public void setBeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
}
}
public class GPBeanDefinitionReader {
//保存扫描的结果
private List<String> regitryBeanClasses = new ArrayList<String>();
private Properties contextConfig = new Properties();
public GPBeanDefinitionReader(String... configLocations) {
doLoadConfig(configLocations[0]);
//扫描配置文件中的配置的相关的类
doScanner(contextConfig.getProperty("scanPackage"));
}
public Properties getConfig(){
return this.contextConfig;
}
public List<GPBeanDefinition> loadBeanDefinitions() {
List<GPBeanDefinition> result = new ArrayList<GPBeanDefinition>();
try {
for (String className : regitryBeanClasses) {
Class<?> beanClass = Class.forName(className);
if(beanClass.isInterface()){continue;}
//保存类对应的ClassName(全类名)
//还有beanName
//1、默认是类名首字母小写
result.add(doCreateBeanDefinition(toLowerFirstCase(beanClass.getSimpleName()), beanClass.getName()));
//2、自定义
//3、接口注入
for (Class<?> i : beanClass.getInterfaces()) {
result.add(doCreateBeanDefinition(i.getName(),beanClass.getName()));
}
}
}catch (Exception e){
e.printStackTrace();
}
return result;
}
private GPBeanDefinition doCreateBeanDefinition(String beanName, String beanClassName) {
GPBeanDefinition beanDefinition = new GPBeanDefinition();
beanDefinition.setFactoryBeanName(beanName);
beanDefinition.setBeanClassName(beanClassName);
return beanDefinition;
}
private void doLoadConfig(String contextConfigLocation) {
InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation.replaceAll("classpath:",""));
try {
contextConfig.load(is);
} catch (IOException e) {
e.printStackTrace();
}finally {
if(null != is){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void doScanner(String scanPackage) {
//jar 、 war 、zip 、rar
URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.","/"));
File classPath = new File(url.getFile());
//当成是一个ClassPath文件夹
for (File file : classPath.listFiles()) {
if(file.isDirectory()){
doScanner(scanPackage + "." + file.getName());
}else {
if(!file.getName().endsWith(".class")){continue;}
//全类名 = 包名.类名
String className = (scanPackage + "." + file.getName().replace(".class", ""));
//Class.forName(className);
regitryBeanClasses.add(className);
}
}
}
//自己写,自己用
private String toLowerFirstCase(String simpleName) {
char [] chars = simpleName.toCharArray();
// if(chars[0] > )
chars[0] += 32;
return String.valueOf(chars);
}
}
public class GPBeanWrapper {
private Object wrapperInstance;
private Class<?> wrappedClass;
public GPBeanWrapper(Object instance) {
this.wrapperInstance = instance;
this.wrappedClass = instance.getClass();
}
public Object getWrapperInstance() {
return wrapperInstance;
}
public Class<?> getWrappedClass() {
return wrappedClass;
}
}
public class GPHandlerMapping {
private Pattern pattern; //URL
private Method method; //对应的Method
private Object controller;//Method对应的实例对象
public GPHandlerMapping(Pattern pattern, Object controller, Method method) {
this.pattern = pattern;
this.method = method;
this.controller = controller;
}
public Pattern getPattern() {
return pattern;
}
public void setPattern(Pattern pattern) {
this.pattern = pattern;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public Object getController() {
return controller;
}
public void setController(Object controller) {
this.controller = controller;
}
}
public class GPHandlerAdapter {
public GPModelAndView handler(HttpServletRequest req, HttpServletResponse resp, GPHandlerMapping handler) throws Exception{
//保存形参列表
//将参数名称和参数的位置,这种关系保存起来
Map<String,Integer> paramIndexMapping = new HashMap<String, Integer>();
//通过运行时的状态去拿到你
Annotation[] [] pa = handler.getMethod().getParameterAnnotations();
for (int i = 0; i < pa.length ; i ++) {
for(Annotation a : pa[i]){
if(a instanceof GPRequestParam){
String paramName = ((GPRequestParam) a).value();
if(!"".equals(paramName.trim())){
// String value = Arrays.toString(params.get(paramName))
// .replaceAll("\\[|\\]","")
// .replaceAll("\\s+",",");
// paramValues[i] = value;
paramIndexMapping.put(paramName,i);
}
}
}
}
//初始化一下
Class<?> [] paramTypes = handler.getMethod().getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
Class<?> paramterType = paramTypes[i];
if(paramterType == HttpServletRequest.class || paramterType == HttpServletResponse.class){
paramIndexMapping.put(paramterType.getName(),i);
}
}
//去拼接实参列表
//http://localhost/web/query?name=Tom&Cat
Map<String,String[]> params = req.getParameterMap();
Object [] paramValues = new Object[paramTypes.length];
for (Map.Entry<String,String[]> param : params.entrySet()) {
String value = Arrays.toString(params.get(param.getKey()))
.replaceAll("\\[|\\]","")
.replaceAll("\\s+",",");
if(!paramIndexMapping.containsKey(param.getKey())){continue;}
int index = paramIndexMapping.get(param.getKey());
//允许自定义的类型转换器Converter
paramValues[index] = castStringValue(value,paramTypes[index]);
}
if(paramIndexMapping.containsKey(HttpServletRequest.class.getName())){
int index = paramIndexMapping.get(HttpServletRequest.class.getName());
paramValues[index] = req;
}
if(paramIndexMapping.containsKey(HttpServletResponse.class.getName())){
int index = paramIndexMapping.get(HttpServletResponse.class.getName());
paramValues[index] = resp;
}
Object result = handler.getMethod().invoke(handler.getController(),paramValues);
if(result == null || result instanceof Void){return null;}
boolean isModelAndView = handler.getMethod().getReturnType() == GPModelAndView.class;
if(isModelAndView){
return (GPModelAndView)result;
}
return null;
}
private Object castStringValue(String value, Class<?> paramType) {
if(String.class == paramType){
return value;
}else if(Integer.class == paramType){
return Integer.valueOf(value);
}else if(Double.class == paramType){
return Double.valueOf(value);
}else {
if(value != null){
return value;
}
return null;
}
}
}
public class GPView {
private File viewFile;
public GPView(File templateFile) {
this.viewFile = templateFile;
}
public void render(Map<String, ?> model, HttpServletRequest req, HttpServletResponse resp) throws Exception {
StringBuffer sb = new StringBuffer();
RandomAccessFile ra = new RandomAccessFile(this.viewFile,"r");
String line = null;
while (null != (line = ra.readLine())){
line = new String(line.getBytes("ISO-8859-1"),"utf-8");
Pattern pattern = Pattern.compile("¥\\{[^\\}]+\\}",Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(line);
while (matcher.find()){
String paramName = matcher.group();
paramName = paramName.replaceAll("¥\\{|\\}","");
Object paramValue = model.get(paramName);
line = matcher.replaceFirst(makeStringForRegExp(paramValue.toString()));
matcher = pattern.matcher(line);
}
sb.append(line);
}
resp.setCharacterEncoding("utf-8");
resp.getWriter().write(sb.toString());
}
//处理特殊字符
public static String makeStringForRegExp(String str) {
return str.replace("\\", "\\\\").replace("*", "\\*")
.replace("+", "\\+").replace("|", "\\|")
.replace("{", "\\{").replace("}", "\\}")
.replace("(", "\\(").replace(")", "\\)")
.replace("^", "\\^").replace("$", "\\$")
.replace("[", "\\[").replace("]", "\\]")
.replace("?", "\\?").replace(",", "\\,")
.replace(".", "\\.").replace("&", "\\&");
}
}
public class GPModelAndView {
private String viewName;
private Map<String,?> model;
public GPModelAndView(String viewName, Map<String, ?> model) {
this.viewName = viewName;
this.model = model;
}
public GPModelAndView(String viewName) {
this.viewName = viewName;
}
public String getViewName() {
return viewName;
}
public Map<String, ?> getModel() {
return model;
}
}
public class GPViewResolver {
private final String DEFAULT_TEMPLATE_SUFFIX = ".html";
private File tempateRootDir;
public GPViewResolver(String templateRoot) {
String templateRootPath = this.getClass().getClassLoader().getResource(templateRoot).getFile();
tempateRootDir = new File(templateRootPath);
}
public GPView resolveViewName(String viewName){
if(null == viewName || "".equals(viewName.trim())){return null;}
viewName = viewName.endsWith(DEFAULT_TEMPLATE_SUFFIX)? viewName : (viewName + DEFAULT_TEMPLATE_SUFFIX);
File templateFile = new File((tempateRootDir.getPath() + "/" + viewName).replaceAll("/+","/"));
return new GPView(templateFile);
}
}
@Data
public class GPAopConfig {
private String pointCut;
private String aspectClass;
private String aspectBefore;
private String aspectAfter;
private String aspectAfterThrow;
private String aspectAfterThrowingName;
}
@Data
public class GPAdvice {
private Object aspect;
private Method adviceMethod;
private String throwName;
public GPAdvice(Object aspect, Method adviceMethod) {
this.aspect = aspect;
this.adviceMethod = adviceMethod;
}
}
/**
* 解析AOP配置的工具类
*/
public class GPAdvisedSupport {
private GPAopConfig config;
private Object target;
private Class targetClass;
private Pattern pointCutClassPattern;
private Map<Method,Map<String,GPAdvice>> methodCache;
public GPAdvisedSupport(GPAopConfig config) {
this.config = config;
}
//解析配置文件的方法
private void parse() {
//把Spring的Excpress变成Java能够识别的正则表达式
String pointCut = config.getPointCut()
.replaceAll("\\.", "\\\\.")
.replaceAll("\\\\.\\*", ".*")
.replaceAll("\\(", "\\\\(")
.replaceAll("\\)", "\\\\)");
//保存专门匹配Class的正则
String pointCutForClassRegex = pointCut.substring(0, pointCut.lastIndexOf("\\(") - 4);
pointCutClassPattern = Pattern.compile("class " + pointCutForClassRegex.substring(pointCutForClassRegex.lastIndexOf(" ") + 1));
//享元的共享池
methodCache = new HashMap<Method, Map<String, GPAdvice>>();
//保存专门匹配方法的正则
Pattern pointCutPattern = Pattern.compile(pointCut);
try{
Class aspectClass = Class.forName(this.config.getAspectClass());
Map<String,Method> aspectMethods = new HashMap<String, Method>();
for (Method method : aspectClass.getMethods()) {
aspectMethods.put(method.getName(),method);
}
for (Method method : this.targetClass.getMethods()) {
String methodString = method.toString();
if(methodString.contains("throws")){
methodString = methodString.substring(0,methodString.lastIndexOf("throws")).trim();
}
Matcher matcher = pointCutPattern.matcher(methodString);
if(matcher.matches()){
Map<String,GPAdvice> advices = new HashMap<String, GPAdvice>();
if(!(null == config.getAspectBefore() || "".equals(config.getAspectBefore()))){
advices.put("before",new GPAdvice(aspectClass.newInstance(),aspectMethods.get(config.getAspectBefore())));
}
if(!(null == config.getAspectAfter() || "".equals(config.getAspectAfter()))){
advices.put("after",new GPAdvice(aspectClass.newInstance(),aspectMethods.get(config.getAspectAfter())));
}
if(!(null == config.getAspectAfterThrow() || "".equals(config.getAspectAfterThrow()))){
GPAdvice advice = new GPAdvice(aspectClass.newInstance(),aspectMethods.get(config.getAspectAfterThrow()));
advice.setThrowName(config.getAspectAfterThrowingName());
advices.put("afterThrow",advice);
}
//跟目标代理类的业务方法和Advices建立一对多个关联关系,以便在Porxy类中获得
methodCache.put(method,advices);
}
}
}catch(Exception e){
e.printStackTrace();
}
}
//根据一个目标代理类的方法,获得其对应的通知
public Map<String,GPAdvice> getAdvices(Method method, Object o) throws Exception {
//享元设计模式的应用
Map<String,GPAdvice> cache = methodCache.get(method);
if(null == cache){
Method m = targetClass.getMethod(method.getName(),method.getParameterTypes());
cache = methodCache.get(m);
this.methodCache.put(m,cache);
}
return cache;
}
//给ApplicationContext首先IoC中的对象初始化时调用,决定要不要生成代理类的逻辑
public boolean pointCutMath() {
return pointCutClassPattern.matcher(this.targetClass.toString()).matches();
}
public void setTargetClass(Class<?> targetClass) {
this.targetClass = targetClass;
parse();
}
public void setTarget(Object target) {
this.target = target;
}
public Class getTargetClass() {
return targetClass;
}
public Object getTarget() {
return target;
}
}
public class GPJdkDynamicAopProxy implements InvocationHandler {
private GPAdvisedSupport config;
public GPJdkDynamicAopProxy(GPAdvisedSupport config) {
this.config = config;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Map<String,GPAdvice> advices = config.getAdvices(method,null);
Object returnValue;
try {
invokeAdivce(advices.get("before"));
returnValue = method.invoke(this.config.getTarget(),args);
invokeAdivce(advices.get("after"));
}catch (Exception e){
invokeAdivce(advices.get("afterThrow"));
throw e;
}
return returnValue;
}
private void invokeAdivce(GPAdvice advice) {
try {
advice.getAdviceMethod().invoke(advice.getAspect());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(),this.config.getTargetClass().getInterfaces(),this);
}
}
/**
* 委派模式
* 职责:负责任务调度,请求分发
*/
public class GPDispatcherServlet extends HttpServlet {
private GPApplicationContext applicationContext;
private List<GPHandlerMapping> handlerMappings = new ArrayList<GPHandlerMapping>();
private Map<GPHandlerMapping,GPHandlerAdapter> handlerAdapters = new HashMap<GPHandlerMapping, GPHandlerAdapter>();
private List<GPViewResolver> viewResolvers = new ArrayList<GPViewResolver>();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//6、委派,根据URL去找到一个对应的Method并通过response返回
try {
doDispatch(req,resp);
} catch (Exception e) {
try {
processDispatchResult(req,resp,new GPModelAndView("500"));
} catch (Exception e1) {
e1.printStackTrace();
resp.getWriter().write("500 Exception,Detail : " + Arrays.toString(e.getStackTrace()));
}
}
}
private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
//完成了对HandlerMapping的封装
//完成了对方法返回值的封装ModelAndView
//1、通过URL获得一个HandlerMapping
GPHandlerMapping handler = getHandler(req);
if(handler == null){
processDispatchResult(req,resp,new GPModelAndView("404"));
return;
}
//2、根据一个HandlerMaping获得一个HandlerAdapter
GPHandlerAdapter ha = getHandlerAdapter(handler);
//3、解析某一个方法的形参和返回值之后,统一封装为ModelAndView对象
GPModelAndView mv = ha.handler(req,resp,handler);
// 就把ModelAndView变成一个ViewResolver
processDispatchResult(req,resp,mv);
}
private GPHandlerAdapter getHandlerAdapter(GPHandlerMapping handler) {
if(this.handlerAdapters.isEmpty()){return null;}
return this.handlerAdapters.get(handler);
}
private void processDispatchResult(HttpServletRequest req, HttpServletResponse resp, GPModelAndView mv) throws Exception {
if(null == mv){return;}
if(this.viewResolvers.isEmpty()){return;}
for (GPViewResolver viewResolver : this.viewResolvers) {
GPView view = viewResolver.resolveViewName(mv.getViewName());
//直接往浏览器输出
view.render(mv.getModel(),req,resp);
return;
}
}
private GPHandlerMapping getHandler(HttpServletRequest req) {
if(this.handlerMappings.isEmpty()){return null;}
String url = req.getRequestURI();
String contextPath = req.getContextPath();
url = url.replaceAll(contextPath,"").replaceAll("/+","/");
for (GPHandlerMapping mapping : handlerMappings) {
Matcher matcher = mapping.getPattern().matcher(url);
if(!matcher.matches()){continue;}
return mapping;
}
return null;
}
@Override
public void init(ServletConfig config) throws ServletException {
//初始化Spring核心IoC容器
applicationContext = new GPApplicationContext(config.getInitParameter("contextConfigLocation"));
//完成了IoC、DI和MVC部分对接
//初始化九大组件
initStrategies(applicationContext);
System.out.println("GP Spring framework is init.");
}
private void initStrategies(GPApplicationContext context) {
// //多文件上传的组件
// initMultipartResolver(context);
// //初始化本地语言环境
// initLocaleResolver(context);
// //初始化模板处理器
// initThemeResolver(context);
//handlerMapping
initHandlerMappings(context);
//初始化参数适配器
initHandlerAdapters(context);
// //初始化异常拦截器
// initHandlerExceptionResolvers(context);
// //初始化视图预处理器
// initRequestToViewNameTranslator(context);
//初始化视图转换器
initViewResolvers(context);
// //FlashMap管理器
// initFlashMapManager(context);
}
private void initViewResolvers(GPApplicationContext context) {
String templateRoot = context.getConfig().getProperty("templateRoot");
String templateRootPath = this.getClass().getClassLoader().getResource(templateRoot).getFile();
File templateRootDir = new File(templateRootPath);
for (File file : templateRootDir.listFiles()) {
this.viewResolvers.add(new GPViewResolver(templateRoot));
}
}
private void initHandlerAdapters(GPApplicationContext context) {
for (GPHandlerMapping handlerMapping : handlerMappings) {
this.handlerAdapters.put(handlerMapping,new GPHandlerAdapter());
}
}
private void initHandlerMappings(GPApplicationContext context) {
if(this.applicationContext.getBeanDefinitionCount() == 0){ return;}
for (String beanName : this.applicationContext.getBeanDefinitionNames()) {
Object instance = applicationContext.getBean(beanName);
Class<?> clazz = instance.getClass();
if(!clazz.isAnnotationPresent(GPController.class)){ continue; }
//相当于提取 class上配置的url
String baseUrl = "";
if(clazz.isAnnotationPresent(GPRequestMapping.class)){
GPRequestMapping requestMapping = clazz.getAnnotation(GPRequestMapping.class);
baseUrl = requestMapping.value();
}
//只获取public的方法
for (Method method : clazz.getMethods()) {
if(!method.isAnnotationPresent(GPRequestMapping.class)){continue;}
//提取每个方法上面配置的url
GPRequestMapping requestMapping = method.getAnnotation(GPRequestMapping.class);
// //demo//query
String regex = ("/" + baseUrl + "/" + requestMapping.value().replaceAll("\\*",".*")).replaceAll("/+","/");
Pattern pattern = Pattern.compile(regex);
//handlerMapping.put(url,method);
handlerMappings.add(new GPHandlerMapping(pattern,instance,method));
System.out.println("Mapped : " + regex + "," + method);
}
}
}
}
@GPController
@GPRequestMapping("/web")
public class MyAction {
@GPAutowired IQueryService queryService;
@GPAutowired IModifyService modifyService;
@GPRequestMapping("/query.json")
public GPModelAndView query(HttpServletRequest request, HttpServletResponse response,
@GPRequestParam("name") String name){
String result = queryService.query(name);
return out(response,result);
}
@GPRequestMapping("/add*.json")
public GPModelAndView add(HttpServletRequest request,HttpServletResponse response,
@GPRequestParam("name") String name,@GPRequestParam("addr") String addr){
try {
String result = modifyService.add(name, addr);
return out(response,result);
}catch (Throwable e){
Map<String,String> model = new HashMap<String,String>();
model.put("detail",e.getCause().getMessage());
model.put("stackTrace", Arrays.toString(e.getStackTrace()));
return new GPModelAndView("500",model);
}
}
@GPRequestMapping("/remove.json")
public GPModelAndView remove(HttpServletRequest request, HttpServletResponse response,
@GPRequestParam("id") Integer id){
String result = modifyService.remove(id);
return out(response,result);
}
@GPRequestMapping("/edit.json")
public GPModelAndView edit(HttpServletRequest request,HttpServletResponse response,
@GPRequestParam("id") Integer id,
@GPRequestParam("name") String name){
String result = modifyService.edit(id,name);
return out(response,result);
}
private GPModelAndView out(HttpServletResponse resp,String str){
try {
resp.getWriter().write(str);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
@GPController
@GPRequestMapping("/")
public class PageAction {
@GPAutowired
IQueryService queryService;
@GPRequestMapping("/first.html")
public GPModelAndView query(@GPRequestParam("teacher") String teacher){
String result = queryService.query(teacher);
Map<String,Object> model = new HashMap<String,Object>();
model.put("teacher", teacher);
model.put("data", result);
model.put("token", "123456");
return new GPModelAndView("first.html",model);
}
}
@Slf4j
public class LogAspect {
//在调用一个方法之前,执行before方法
public void before(){
//这个方法中的逻辑,是由我们自己写的
log.info("Invoker Before Method!!!");
}
//在调用一个方法之后,执行after方法
public void after(){
log.info("Invoker After Method!!!");
}
public void afterThrowing(){
log.info("出现异常");
}
}
404.html:
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>页面去火星了</title>
</head>
<body>
<font size='25' color='red'>404 Not Found</font><br/><font color='green'><i>Copyright@GupaoEDU</i></font>
</body>
</html>
500.html:
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>服务器好像累了</title>
</head>
<body>
<font size='25' color='blue'>500 服务器好像有点累了,需要休息一下</font><br/>
<b>Message:¥{detail}</b><br/>
<b>StackTrace:¥{stackTrace}</b><br/>
<font color='green'><i>Copyright@GupaoEDU</i></font>
</body>
</html>
first.html
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>CharlesDu SpringMVC模板引擎演示</title>
</head>
<center>
<h1>大家好,我是¥{teacher}老师<br/>欢迎大家一起来探索Spring的世界</h1>
<h3>Hello,My name is ¥{teacher}</h3>
<div>¥{data}</div>
Token值:¥{token}
</center>
</html>