AndServer官方地址:入门 · GitBook
1.在安卓项目的两个build.grade中添加相关依赖:
2.目录结构:
以我写的顺序去进行理解:
首先创建一个server的管理类:进行初始化,启动,停止操作等
import android.content.Context;
import android.util.Log;import com.yanzhenjie.andserver.AndServer;
import com.yanzhenjie.andserver.Server;import java.util.concurrent.TimeUnit;
public class ServerManager {private Server mServer;private static ServerManager instance;private ServerManager(Context context) {mServer = AndServer.webServer(context).port(8080).timeout(10, TimeUnit.SECONDS).listener(new Server.ServerListener() {@Overridepublic void onStarted() {// TODO The server started successfully.}@Overridepublic void onStopped() {// TODO The server has stopped.}@Overridepublic void onException(Exception e) {// TODO An exception occurred while the server was starting.}}).build();}public static ServerManager getInstance(Context context) {if (instance == null) {instance = new ServerManager(context);}return instance;}public void startServer() {if (mServer.isRunning()) {// TODO The server is already up.} else {mServer.startup();}}public void stopServer() {if (mServer.isRunning()) {mServer.shutdown();} else {Log.w("AndServer", "The server has not started yet.");}}
}
在mainactivity中增加启动代码:
其实这个时候运行到真机或者模拟机上时就已经启动了,为了方便测试,增加几个测试接口:
@RestController
@RequestMapping(path = "/api")
public class TestController {@GetMapping("/user/get")public String test(@RequestParam("id") String id) {return "id = " + id;}
}
通过浏览器访问安卓设备的IP:8080/api/user/get?id=1会看到浏览器出现id=1的字样
配置web网站的目录:
@Config
public class AppConfig implements WebConfig {@Overridepublic void onConfig(Context context, Delegate delegate) {// 增加一个位于assets的web目录的网站delegate.addWebsite(new AssetsWebsite(context, "/web/"));}
}
这样网页就被映射到assets下的web目录中:
可以通过page去测试:
@Controller
public class PageController {@GetMapping("/")public String index() {return "forward:/index.html";}@GetMapping("/page")public String page() {return "forward:/page.html";}
}
访问根目录:
访问page:
启动已经🆗那么也需要在activity销毁时进行服务的关闭操作:
这个时候已经完成了基本的流程的,那么如何进行登录状态的保存以及拦截呢?
因为一般在安卓终端设备中都是相对比较简单的项目,那么本次我采用的登录状态保存方式是session(当然你可以使用其他方式,原理类似)
编写一个拦截类:
@Interceptor
public class AuthInterceptor implements HandlerInterceptor {@Overridepublic boolean onIntercept(@NonNull HttpRequest request, @NonNull HttpResponse response, @NonNull RequestHandler handler) throws Exception {String path = request.getPath();Log.w("AuthInterceptor", "path = " + path);if (path.startsWith("/api/")) {Session session = request.getSession(); // 获取现有 Session,不创建新 Sessionif (session == null || session.getAttribute("user") == null) {response.setStatus(StatusCode.SC_UNAUTHORIZED);// 将字符串转换为字节数组String responseBodyString = "Unauthorized access. Please login first.";StringResponseBody responseBody = new StringResponseBody(responseBodyString);response.setBody(responseBody);return true; // 拦截请求}return false; // 放行请求}return false; // 放行请求}
}
这里只拦截了以api开头的url 需要登录状态去访问
注意:返回false是不拦截 true是拦截
这里通过
@Interceptor
这种注释方式去进行拦截
StringResponseBody代码
public class StringResponseBody implements ResponseBody {private String content;public StringResponseBody(String content) {this.content = content;}@Overridepublic boolean isRepeatable() {return true; // Assuming it is repeatable}@Overridepublic boolean isChunked() {return false; // Not chunked}@Overridepublic long contentLength() {return content.length();}@Nullable@Overridepublic MediaType contentType() {return null;}@Overridepublic void writeTo(@NonNull OutputStream output) throws IOException {output.write(content.getBytes());}
}
访问:
结束 告辞