spring小demo优化
还是在GPDispatcherServlet这个类里创建所需要的容器如下:
//模拟ioc容器
private Map<String, Object> ioc = new HashMap<>();
//保存配置文件application.properties中的内容
private Properties contextConfig=new Properties();
//存放包内扫描到的类名
private List<String> classNames=new ArrayList<>();
//保存url和method之间的关系
private List<Handler> handlerMapping=new ArrayList<>();
init方法如下:
//加载配置文件
doLoadConfig(config.getInitParameter("contextConfigLocation"));
//扫描相关的类
doScanner(contextConfig.getProperty("scanPackage"));
//初始化扫描到的类,并且把他们放到ioc容器中
try {
doInstance();
} catch (Exception e) {
e.printStackTrace();
}
//完成依赖注入
doAutowired();
//初始化HandlerMapping
initHandlerMapping();
具体方法如下:
private void doLoadConfig(String contextConfigLocation){
InputStream is=this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
try {
contextConfig.load(is);
} catch (IOException e) {
e.printStackTrace();
}finally {
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void doInstance() throws Exception {
if(classNames.isEmpty()){
return;
}
for(String className:classNames){
try {
Class<?> clazz=Class.forName(className);
if(clazz.isAnnotationPresent(GPController.class)){
Object instance=clazz.newInstance();
String beanName=clazz.getSimpleName().toLowerCase();
ioc.put(beanName,instance);
}
if(clazz.isAnnotationPresent(GPService.class)){
Object instance=clazz.newInstance();
GPService gpService=clazz.getAnnotation(GPService.class);
String beanName=gpService.value();
if("".equals(beanName)){
beanName=clazz.getSimpleName();
}
for(Class<?> i:clazz.getInterfaces()){
if(ioc.containsKey(i.getName())){
throw new Exception(i.getName()+"is exists");
}
ioc.put(i.getName(),instance);
}
ioc.put(beanName,instance);
}else{
continue;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
private void doAutowired(){
if(ioc.isEmpty()){
return;
}
for(Map.Entry<String,Object> entry:ioc.entrySet()){
Field [] fields=entry.getValue().getClass().getDeclaredFields();
for(Field field:fields){
if(!field.isAnnotationPresent(GPAutowired.class)){
continue;
}
GPAutowired gpAutowired=field.getAnnotation(GPAutowired.class);
String beanName=gpAutowired.value().trim();
if("".equals(beanName)){
beanName=field.getType().getName();
}
field.setAccessible(true);
try {
field.set(entry.getValue(),ioc.get(beanName));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
private void initHandlerMapping(){
if(ioc.isEmpty()){
return;
}
for(Map.Entry<String,Object> entry:ioc.entrySet()){
Class<?> clazz=entry.getValue().getClass();
if(!clazz.isAnnotationPresent(GPController.class)){
continue;
}
String baseUrl="";
if(clazz.isAnnotationPresent(GPRequestMapping.class)){
GPRequestMapping gpRequestMapping=clazz.getAnnotation(GPRequestMapping.class);
baseUrl=gpRequestMapping.value();
}
for(Method method:clazz.getMethods()){
if(!method.isAnnotationPresent(GPRequestMapping.class)){
continue;
}
GPRequestMapping requestMapping=method.getAnnotation(GPRequestMapping.class);
String regex=("/"+baseUrl+"/"+requestMapping.value()).replaceAll("/+","/");
Pattern pattern=Pattern.compile(regex);
handlerMapping.add(new Handler(pattern,entry.getValue(),method));
}
}
}
private void doScanner(String scanPackage) {
URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
File classDir = new File(url.getFile());
for (File file : classDir.listFiles()) {
if (file.isDirectory()) {
doScanner(scanPackage + "." + file.getName());
} else {
if (!file.getName().endsWith(".class")) {
continue;
}
String clzName = (scanPackage + "." + file.getName()).replaceAll(".class", "");
classNames.add(clzName);
}
}
}
doGet和doPost方法如下:
@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 {
try {
doDispathch(req, resp);
} catch (Exception e) {
e.printStackTrace();
resp.getWriter().print("500" + Arrays.toString(e.getStackTrace()));
}
}
doDispathch方法如下:
private void doDispathch(HttpServletRequest request, HttpServletResponse response) throws InvocationTargetException, IllegalAccessException, IOException {
// if (!this.handlerMapping.containsKey(url)) {
Handler handler=getHandler(request);
if(handler==null){
response.getWriter().print("404 NOT FOUND");
return;
}
Method method = handler.method;
Map<String, String[]> params = request.getParameterMap();
Map<String, String[]> parameterMap = request.getParameterMap();
Class<?> [] parameterTypes=method.getParameterTypes();
Object [] paramValues=new Object[parameterTypes.length];
for(Map.Entry<String,String []> entry:params.entrySet()){
String value= Arrays.toString(entry.getValue()).replaceAll("\\[|\\]","").replaceAll("\\s","");
if(!handler.paramIndexMapping.containsKey(entry.getKey())){
continue;
}
int index=handler.paramIndexMapping.get(entry.getKey());
paramValues[index]=convert(parameterTypes[index],value);
}
if(handler.paramIndexMapping.containsKey(HttpServletRequest.class.getName())){
int reqIndex=handler.paramIndexMapping.get(HttpServletRequest.class.getName());
paramValues[reqIndex]=request;
}
if (handler.paramIndexMapping.containsKey(HttpServletResponse.class.getName())) {
int respIndex=handler.paramIndexMapping.get(HttpServletResponse.class.getName());
paramValues[respIndex]=response;
}
Object returnValue=handler.method.invoke(handler.controller,paramValues);
if(returnValue==null||returnValue instanceof Void){
return;
}
response.getWriter().print(returnValue.toString());
}
convert方法如下:
private Object convert(Class<?> type,String valure){
if(Integer.class==type){
return Integer.valueOf(valure);
}
//其他类型也可做对应的转换
return valure;
}
相信完成这个小demo之后,你对spring、springMVC有了一个初步的认知。